Treat child as field of parent in elastic search query

Viewed 16843

I am reading the docs for elasticsearch and this [page][1] talks about mapping a child to a parent type using _parent.

If I have childs called email attached to parents called account:

Fields in each type:

account (http://localhost:9200/myapp/account/1)
========
id
name
some_other_info
state

email (http://localhost:9200/myapp/email/1?parent=1)
========
id
email
  • How can I search on the name field of account and the email field of email provided that the state of account is active?

  • Is there a way to get all the children (of a certain type or of any type) a parent owns?

  • When indexing a child document, is it possible to to pass the parent as an object property in the JSON data as opposed to it being part of the query string?


After trying imotov's suggestion, I came up with this query:

This is executed on http://localhost:9200/myapp/account/_search

{
  "query": {
    "bool": {
      "must": [
        {
          "prefix": {
            "name": "a"
          }
        },
        {
          "term": {
            "statuses": "active"
          }
        }
      ],
      "should": [
        {
          "has_child": {
            "type": "emailaddress",
            "query": {
              "prefix": {
                "email": "a"
              }
            }
          }
        }
      ]
    }
  }
}

The problem is that the above does not give me any accounts where the email matches.

The effect I want is essentially this:

  • There is one search box
  • Users start typing and the search box autocompletes.
  • The user's query is checked against the name of the account or any of the emailaddress type.
  • If accounts were matched, just return them. If emailaddress were match, return its parent account.
  • Limit to a maximum of x (say 10) accounts for each search.

So, I basically need to be able to OR the search between 2 types and return the parent type of matches.


Test data:

curl -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 relationship

curl -XPUT 'http://localhost:9200/test/email/_mapping' -d '{
    "emails" : {
        "_parent" : {"type" : "account"}
    }
}'

curl -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"
}'

imotov's solution worked for me. Another solution I have found is to query accounts for status = active, then run a bool filter on the result and use has_child on the child type and prefix on name inside the bool filter.

1 Answers
Related