Search code examples
elasticsearchkibana

Elastic search query in array of json object


So, I have a metadata data field in my index which is in the following format.

metadata: [
 {
    "key": "type",
    "value": "animal"
 },
 {
    "key": "animal",
    "value": "cat"
 }
]

The array can have thousands of objects, and I cannot change the structure of this field.
My client application requests the server with key=value format. How do I write elastic search query to get the result?

Request query type=animal should return only 1st object from the array (not 2nd).
Request query animal=cat should return only 2nd object from the array (not 1st).
Request query type=cat should not return anything.

How can it be achieved? I am worn out trying to figure out the correct query.


Solution

  • According to your question, you have to return only the matching object from the array based on the query.

    On the basis of Elasticsearch Array docs

    Arrays of objects do not work as you would expect: you cannot query each object independently of the other objects in the array. If you need to be able to do this then you should use the nested datatype instead of the object datatype.

    If you want to query on each object of the array and return only the specific object from the array, you need to use a nested query with inner_hits. But for using the nested query, you have to create a new index with nested mapping

    Adding a working example with index mapping, index data, search query, and search result

    Index Mapping:

    PUT <index-name>
    {
      "mappings": {
        "properties": {
          "metadata":{
            "type":"nested"
          }
        }
      }
    }
    

    Index Data:

    POST <index-name>/_doc/1
    {
      "metadata": [
        {
          "key": "type",
          "value": "animal"
        },
        {
          "key": "animal",
          "value": "cat"
        }
      ]
    }
    

    Search Query:

    POST <index-name>/_search
    {
      "query": {
        "nested": {
          "path": "metadata",
          "query": {
            "match": {
              "metadata.key": "animal"
            }
          },
          "inner_hits": {}
        }
      }
    }
    

    Search Result:

    "inner_hits" : {
              "metadata" : {
                "hits" : {
                  "total" : {
                    "value" : 1,
                    "relation" : "eq"
                  },
                  "max_score" : 0.6931471,
                  "hits" : [
                    {
                      "_index" : "70711376",
                      "_type" : "_doc",
                      "_id" : "1",
                      "_nested" : {
                        "field" : "metadata",
                        "offset" : 1
                      },
                      "_score" : 0.6931471,
                      "_source" : {
                        "value" : "cat",
                        "key" : "animal"
                      }
                    }
                  ]
                }
              }
            }