0

I didn't find any answers how to do simple thing in ElasticSearch 6.8 I need to filter nested objects.

Index

{
  "settings": {
    "index": {
      "number_of_shards": "5",
      "number_of_replicas": "1"
    }
  },
  "mappings": {
    "human": {
      "properties": {
        "cats": {
          "type": "nested",
          "properties": {
            "name": {
              "type": "text"
            },
            "breed": {
              "type": "text"
            },
            "colors": {
              "type": "integer"
            }
          }
        },
        "name": {
          "type": "text"
        }
      }
    }
  }
}

Data

{
  "name": "iridakos",
  "cats": [
    {
      "colors": 1,
      "name": "Irida",
      "breed": "European Shorthair"
    },
    {
      "colors": 2,
      "name": "Phoebe",
      "breed": "european"
    },
    {
      "colors": 3,
      "name": "Nino",
      "breed": "Aegean"
    }
  ]
}

select human with name="iridakos" and cats with breed contains 'European' (ignore case). Only two cats should be returned.

Million thanks for helping.

2 Answers 2

1

For nested datatypes, you would need to make use of nested queries.

Elasticsearch would always return the entire document as a response. Note that nested datatype means that every item in the list would be treated as an entire document in itself.

Hence in addition to return entire document, if you also want to know the exact hits, you would need to make use of inner_hits feature.

Below query should help you.

POST <your_index_name>/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "iridakos"
          }
        },
        {
          "nested": {
            "path": "cats",
            "query": {
              "match": {
                "cats.breed": "european"
              }
            },
            "inner_hits": {}
          }
        }
      ]
    }
  }
}

Response:

{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.74455214,
    "hits" : [
      {
        "_index" : "my_cat_index",
        "_type" : "_doc",
        "_id" : "1",                           <--- The document that hit
        "_score" : 0.74455214,
        "_source" : {
          "name" : "iridakos",
          "cats" : [
            {
              "colors" : 1,
              "name" : "Irida",
              "breed" : "European Shorthair"
            },
            {
              "colors" : 2,
              "name" : "Phoebe",
              "breed" : "european"
            },
            {
              "colors" : 3,
              "name" : "Nino",
              "breed" : "Aegean"
            }
          ]
        },
        "inner_hits" : {                       <---- Note this
          "cats" : {
            "hits" : {
              "total" : {
                "value" : 2,                   <---- Count of nested doc hits
                "relation" : "eq"
              },
              "max_score" : 0.52354836,
              "hits" : [
                {
                  "_index" : "my_cat_index",
                  "_type" : "_doc",
                  "_id" : "1",
                  "_nested" : {
                    "field" : "cats",
                    "offset" : 1
                  },
                  "_score" : 0.52354836,
                  "_source" : {                       <---- First Nested Document 
                    "breed" : "european"              
                  }
                },
                {
                  "_index" : "my_cat_index",
                  "_type" : "_doc",
                  "_id" : "1",
                  "_nested" : {
                    "field" : "cats",
                    "offset" : 0
                  },
                  "_score" : 0.39019167,
                  "_source" : {                       <---- Second Document
                    "breed" : "European Shorthair"
                  }
                }
              ]
            }
          }
        }
      }
    ]
  }
}

Note in your response how the inner_hits section would appear where you would find the exact hits.

Hope this helps!

Sign up to request clarification or add additional context in comments.

Comments

0

You could use something like this:

{
  "query": { 
    "bool": { 
      "must": [
        { "match": { "name":   "iridakos" }},
        { "match": { "cats.breed": "European" }}
      ]
    }
  }
}

To search on a cat's breed, you can use the dot-notation.

3 Comments

Thank you for answer. But how to filter nested cats? I need to return only 2 nested "cats" in parent "human" object
This is incorrect. And doesn't work. Notice the datatype of cats, it is nested and not object type.
@boris_dev looks like you can use a "nested" query like in here elastic.co/guide/en/elasticsearch/reference/current/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.