Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Having trouble creating Parent-Child Relationship in ElasticSearch 6

I'm currently working through an ElasticSearch course on Udemy, but the video is talking about ElasticSearch 5 and I am currently using ElasticSearch 6. I'm having trouble translating the parent/child relationships in to the new format.

In the video is setting up Franchise with Films (i.e. Star Wars and The Jedi Returns respectively.

The tutor does the following:

curl -H "Content-Type: application/json" -XPUT "127.0.0.1:9200/series" -d '
{
    "mappings": {
        "franchise": {},
        "film": {
            "_parent": {
                "type": "franchise"
            }
        }
    }
}'

However when I try adding the mappings I get the following errors:

➜  Downloads curl -H "Content-Type: application/json" -XPUT "127.0.0.1:9200/series?pretty" -d '
{
    "mappings": {
        "franchise": {},
        "film": {
            "_parent": {
                "type": "franchise"
            }
        }
    }
}'
{
  "error" : {
    "root_cause" : [
      {
        "type" : "illegal_argument_exception",
        "reason" : "Rejecting mapping update to [series] as the final mapping would have more than 1 type: [franchise, film]"
      }
    ],
    "type" : "illegal_argument_exception",
    "reason" : "Rejecting mapping update to [series] as the final mapping would have more than 1 type: [franchise, film]"
  },
  "status" : 400
}

I have tried a number of things based on the following resources but have not been able to find a soluton: https://www.elastic.co/blog/index-type-parent-child-join-now-future-in-elasticsearch https://www.elastic.co/guide/en/elasticsearch/reference/master/parent-join.html https://github.com/elastic/elasticsearch/issues/20257

TLDR: Can someone please help me translate a parent-child relationship from ElastiSearch 5 to the correct way of doing it in ElasticSearch 6?


Next step (Validation): As a validation to see if the mapping is working, the tutor then did the following:

He gets the following JSON data:

wget http://media.sundog-soft.com/es/series.json

Extract from JSON file:

{ "create" : { "_index" : "series", "_type" : "franchise", "_id" : "1"} }
{ "id": "1", "title" : "Star Wars" }
{ "create" : { "_index" : "series", "_type" : "film", "_id" : "260", "parent" : "1" } }
{ "id": "260", "title" : "Star Wars: Episode IV - A New Hope", "year":"1977" , "genre":["Action", "Adventure", "Sci-Fi"] }

And bulk imports data by doing the following:

➜  curl -H "Content-Type: application/json" -XPUT "127.0.0.1:9200/_bulk?pretty" --data-binary @series.json
like image 287
8bithero Avatar asked Dec 05 '22 12:12

8bithero


1 Answers

With Elasticsearch 6.0, there are some fundamental changes which prevent parent/child relationships.

  1. One index cannot contain more than one type. Read more here.
  2. Parent/child relationships have been removed, and hence the _parent field is also removed. You have to use join field instead of parent/child.

Parent/child relationships required that there were two distinct types and both types were defined in the same index. Now that you can't have multiple types in one index, there is no way parent/child relationships can be supported in the same way that they were supported in 5.x and prior releases.

You can refer to the join field documentation to see how to do similar things to parent/child relationships. But now, you have to define both kinds of documents within a single Elasticsearch index, within the same type. Please see the example which explains how to model "1 to many" kind of relationships (1 question, multiple answers related to that question) using a join field here.

EDIT:

The example, updated for Elasticsearch 6.x with the use of join field would look as follows.

Drop your existing index if it exists.

curl -XDELETE "http://localhost:9200/series"

Create new index with join field, that establishes join relationship between franchise & film:

curl -XPUT "http://localhost:9200/series" -H 'Content-Type: application/json' -d'
{
  "mappings": {
    "doc": {
      "properties": {
        "join_field": { 
          "type": "join",
          "relations": {
            "franchise": "film" 
          }
        }
      }
    }
  }
}'

The updated series.json from your example to be sent as an inline bulk request:

curl -XPOST "http://localhost:9200/_bulk" -H 'Content-Type: application/json' -d'
{ "create" : { "_index" : "series", "_type" : "doc", "_id" : "1"} }
{ "id": "1", "title" : "Star Wars", "join_field": "franchise" }
{ "create" : { "_index" : "series", "_type" : "doc", "_id" : "260", "routing" : "1" } }
{ "id": "260", "title" : "Star Wars: Episode IV - A New Hope", "year":"1977" , "genre":["Action", "Adventure", "Sci-Fi"], "join_field": {"name": "film", "parent": "1"} }
{ "create" : { "_index" : "series", "_type" : "doc", "_id" : "1196", "routing" : "1" } }
{ "id": "1196", "title" : "Star Wars: Episode V - The Empire Strikes Back", "year":"1980" , "genre":["Action", "Adventure", "Sci-Fi"], "join_field": {"name": "film", "parent": "1"} }
{ "create" : { "_index" : "series", "_type" : "doc", "_id" : "1210", "routing" : "1" } }
{ "id": "1210", "title" : "Star Wars: Episode VI - Return of the Jedi", "year":"1983" , "genre":["Action", "Adventure", "Sci-Fi"], "join_field": {"name": "film", "parent": "1"} }
{ "create" : { "_index" : "series", "_type" : "doc", "_id" : "2628", "routing" : "1" } }
{ "id": "2628", "title" : "Star Wars: Episode I - The Phantom Menace", "year":"1999" , "genre":["Action", "Adventure", "Sci-Fi"], "join_field": {"name": "film", "parent": "1"} }
{ "create" : { "_index" : "series", "_type" : "doc", "_id" : "5378", "routing" : "1" } }
{ "id": "5378", "title" : "Star Wars: Episode II - Attack of the Clones", "year":"2002" , "genre":["Action", "Adventure", "Sci-Fi", "IMAX"], "join_field": {"name": "film", "parent": "1"} }
{ "create" : { "_index" : "series", "_type" : "doc", "_id" : "33493", "routing" : "1" } }
{ "id": "33493", "title" : "Star Wars: Episode III - Revenge of the Sith", "year":"2005" , "genre":["Action", "Adventure", "Sci-Fi"], "join_field": {"name": "film", "parent": "1"} }
{ "create" : { "_index" : "series", "_type" : "doc", "_id" : "122886", "routing" : "1" } }
{ "id": "122886", "title" : "Star Wars: Episode VII - The Force Awakens", "year":"2015" , "genre":["Action", "Adventure", "Fantasy", "Sci-Fi", "IMAX"], "join_field": {"name": "film", "parent": "1"} }
'

The bulk request above creates one franchise and multiple films that are related with that franchise.

To query all films that have the franchise id = 1, use the following parent id query.

curl -XGET "http://localhost:9200/series/_search" -H 'Content-Type: application/json' -d'
{
  "query": {
    "parent_id": { 
      "type": "film",
      "id": "1"
    }
  }
}'
like image 139
Pranav Shukla Avatar answered May 16 '23 05:05

Pranav Shukla