boris_dev
boris_dev

Reputation: 232

Filter nested objects in ElasticSearch 6.8.1

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.

Upvotes: 0

Views: 720

Answers (2)

Kamal Kunjapur
Kamal Kunjapur

Reputation: 8840

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!

Upvotes: 1

TheDude
TheDude

Reputation: 3952

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.

Upvotes: 0

Related Questions