Parent-child relationships

Similar to nested types, parent-child relationships also allow you to relate different entities together but they differ in the implementation and behavior. Unlike nested documents, they are not present within the same document, rather parent-child documents are completely separate documents. They follow the one to many relationship principle and allow you to define one type as parent and one or more as the child type.

Creating parent-child mappings

To create a parent-child mapping, you just need to specify which type should be the parent of the child type. You do not need to define anything extra in the parent type mapping but before indexing the data in the child type, you need to specify in the child's mapping who will be its parent.

Let's create a new index, twitter_parent_child:

PUT /twitter_parent_child

Now, put the mapping of the tweets type by specifying that the user will be its parent. This is done using the _parent keyword inside the mapping, but outside the properties:

PUT /twitter_parent_child/tweets/_mapping
{
  "_parent": {
    "type": "users"
  },
  "properties": {
    "text":{"type": "string"},
    "created_at":{"type": "date"}
  }
}

Next, put the mapping of the users type:

PUT /twitter_parent_child/users/_mapping
{
  "properties": {
    "screen_name":{"type": "string"},
    "created_at":{"type": "date"}
  }
}

Note

One parent can have multiple child types but one child can have only one parent type. It's also important to know the fact that you have to create the mappings for child type and specify the parent before creating the parent type. If you do it in reverse, you will get the exception: "Can't add a _parent field that points to an already existing type". Also, note that parents cannot be updated for any child type.

Indexing parent-child documents

Indexing parent documents is similar to what we have followed till now. However, while indexing children, you need to specify the unique ID of the parent document so that Elasticsearch can know which document is the parent of this document.

Python example

Indexing parent document:

A parent document is indexed in a similar way to any other document:

parent_doc = {}parent_doc['screen_name'] = 'd_bharvi'parent_doc['followers_count"'] = 2000parent_doc['create_at"'] = '2012-05-30'
es.index(index='twitter_parent_child', doc_type= users, body=parent_doc, id='64995604')

Indexing a child document:

Indexing a child document requires specifying the _id of the parent document type. In Python, it is done using the id parameter inside the index function:

child_doc = {}
child_doc['text'] = 'learning parent-child concepts'
child_doc['created_at'] = '2015-10-30'
es.index(index='twitter_parent_child', doc_type= 'tweets', body=child_doc, id = '2333', parent='64995604')

Java example

Include the following import statements:

import org.elasticsearch.action.index.IndexRequestBuilder;

The parent document can be indexed in the following way:

IndexRequestBuilder index = client.prepareIndex( "twitter_parent_child", "users");
Map<String, Object> parentDoc= new HashMap<String, Object>();
parentDoc.put("screen_name", "d_bharvi");
parentDoc.put("followers_count", 2000);
parentDoc.put("create_at", "2012-05-30");
index.setId("64995604").setSource(parentDoc)
.execute().actionGet();

The child document can be indexed in the following way:

IndexRequestBuilder index=client.prepareIndex("twitter_parent_child", "tweets");
Map<String, Object> childDoc= new HashMap<String, Object>();
childDoc.put("text", "learning parent-child concepts in elasticsearch");
childDoc.put("create_at", "2015-05-30");
index.setParent("64995604").setId("2333")
.setSource(childDoc).execute().actionGet();

Please note that while indexing the child document, we have used the setParent method and passed the _id of the parent document.

Note

By specifying the parent ID, we not only create an association between the parent and child documents but also make sure that they reside in the same shard.

Querying parent-child documents

Elasticsearch offers two queries to search parent-child documents:

  • The has_child query
  • The has_parent query

has_child query

The has_child query allows you to find and return parent documents by querying the child type. For example, we can find all the users who have tweeted about Elasticsearch.

Python exam ple

query = {
  "query": {
    "has_child": {
      "type": "tweets",
      "query": {
        "match": {
          "text": "elasticsearch"
        }
      }
    }
  }
}
resp = es.search(index='twitter_parent_child', doc_type= 'users', body=query)

Java example

The same query can be applied using Java with the following code:

SearchResponse response = client.prepareSearch("twitter_parent_child").setTypes("users")
  .setQuery(QueryBuilders.hasChildQuery(childType,   QueryBuilders.matchQuery("text","elasticsearch")))
  .execute().actionGet();

Note

Please see carefully that while using the has_child query, it is applied to the parent type because we have to return the parent documents, while the has_child parameter contains the name of the child type.

has_parent query

The has_parent query works in reverse compared to the has_child query and allows you to find and return child documents by querying on the parent type. For example, we can find all the tweets tweeted by users who have a followers count greater than 200.

Python example

query = {
  "query": {
    "has_parent": {
      "type": "users",
      "query": {
        "range": {
          "followers_count": {
            "gte": 200
          }
        }
      }
    }
  }
}
resp = es.search(index='twitter_parent_child', doc_type= 'tweets', body=query)

Java example

The same query can be applied using Java with the following code:

SearchResponse response = client.prepareSearch("twitter_parent_child")
      .setTypes("tweets")
      .setQuery(QueryBuilders
      .hasParentQuery(parentType, QueryBuilders.rangeQuery("followers_count")
      .gt(200))).execute().actionGet();
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset