Treat child as field of parent in elastic search query Treat child as field of parent in elastic search query elasticsearch elasticsearch

Treat child as field of parent in elastic search query


An important difference between elasticsearch and relational databases is that elasticsearch cannot perform joins. In elasticsearch you are always searching a single index or union of indices. But in case of parent/child relationship, it's possible to limit results in the parent index using a query on the child index. For example, you can execute this query on the account type.

{    "bool": {        "must": [            {                 "text" : { "name": "foo" }             }, {                 "term" : { "state": "active" }             }, {                "has_child": {                    "type": "email",                    "query": {                        "text": {"email": "bar" }                    }                }            }        ]    }}

This query will return you the parent document only (no child documents will be returned). You can use the parent id returned by this query to find all children of this parent using the field _parent, which is stored and indexed by default.

{    "term" : { "_parent": "1" } }

Or you can limit your results only to the children that contain the word bar in the field email:

{    "bool": {        "must": [            {                 "term" : { "_parent": "1" }             }, {                 "text" : { "email": "bar" }             }        ]    }}

I don't think it's possible to specify parent in the json unless you are using _bulk indexing.

This is how email lookup can be implemented using test data provided in the question:

#!/bin/shcurl -XDELETE 'http://localhost:9200/test' && echo curl -XPOST 'http://localhost:9200/test' -d '{    "settings" : {        "number_of_shards" : 1,        "number_of_replicas" : 0    },    "mappings" : {      "account" : {        "_source" : { "enabled" : true },        "properties" : {          "name": { "type": "string", "analyzer": "standard" },          "statuses": { "type": "string",  "index": "not_analyzed" }        }      },      "email" : {        "_parent" : {          "type" : "account"        },        "properties" : {          "email": { "type": "string",  "analyzer": "standard" }        }      }    }}' && echocurl -XPUT 'http://localhost:9200/test/account/1' -d '{    "name": "John Smith",    "statuses": "active"}'curl -XPUT 'http://localhost:9200/test/account/2' -d '{    "name": "Peter Smith",    "statuses": "active"}'curl -XPUT 'http://localhost:9200/test/account/3' -d '{    "name": "Andy Smith",    "statuses": "active"}'//Set up mapping for parent/child relationshipcurl -XPUT 'http://localhost:9200/test/email/1?parent=1' -d '{    "email": "john@smith.com"}'curl -XPUT 'http://localhost:9200/test/email/2?parent=1' -d '{    "email": "admin@mycompany.com"}'curl -XPUT 'http://localhost:9200/test/email/3?parent=1' -d '{    "email": "abcd@efg.com"}'curl -XPUT 'http://localhost:9200/test/email/4?parent=2' -d '{    "email": "peter@peter.com"}'curl -XPUT 'http://localhost:9200/test/email/5?parent=3' -d '{    "email": "andy@yahoo.com"}'curl -XPUT 'http://localhost:9200/test/email/6?parent=3' -d '{    "email": "support@mycompany.com"}'curl -XPOST 'http://localhost:9200/test/_refresh'echocurl 'http://localhost:9200/test/account/_search' -d '{  "query": {    "bool": {      "must": [        {          "term": {            "statuses": "active"          }        }      ],      "should": [        {          "prefix": {            "name": "a"          }        },        {          "has_child": {            "type": "email",            "query": {              "prefix": {                "email": "a"              }            }          }        }      ],      "minimum_number_should_match" : 1    }  }}' && echo