search first element of a multivalue text field in elasticsearch

Viewed 472

I want to search first element of array in documents of elasticsearch, but I can't.

I don't find it that how can I search.

For test, I created new index with fielddata=true, but I still didn't get the response that I wanted

Document

      "name" : {
        "type" : "text",
        "fields" : {
          "keyword" : {
            "type" : "keyword",
            "ignore_above" : 256
          }
        }
      },

Values

name : ["John", "Doe"]

My request

{
    "query": {
        "bool" : {
            "must" : {
                "script" : {
                    "script" : {
                        "source": "doc['name'][0]=params.param1",
                                                "params" : {
                            "param1" : "john"
                        }
                     }
                }
            }
        }
    }
}

Incoming Response

"reason": "Fielddata is disabled on text fields by default. Set fielddata=true on [name] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead."
2 Answers

You can use the following script that is used in a search request to return a scripted field:

{
  "script_fields": {
    "firstElement": {
      "script": {
        "lang":   "painless",
        "inline": "params._source.name[0]"
      }
    }
  }
}

Search Result:

"hits": [
      {
        "_index": "stof_64391432",
        "_type": "_doc",
        "_id": "1",
        "_score": 1.0,
        "fields": {
          "firstElement": [
            "John"             <-- note this
          ]
        }
      }
    ]

You can use a Painless script to create a script field to return a customized value for each document in the results of a query.

You need to use equality equals operator '==' to COMPARE two values where the resultant boolean type value is true if the two values are equal and false otherwise in the script query.

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

Index Mapping:

{
  "mappings":{
    "properties":{
      "name":{
        "type":"text",
        "fielddata":true
      }
    }
  }
}

Index data:

{
  "name": [
    "John",
    "Doe"
  ]
}

Search Query:

{
  "script_fields": {
    "my_field": {
      "script": {
        "lang":   "painless",
        "source": "params['_source']['name'][0] == params.params1",
        "params": {
          "params1": "John"
        }
      }
    }
  }
}

Search Result:

"hits": [
      {
        "_index": "test",
        "_type": "_doc",
        "_id": "1",
        "_score": 1.0,
        "fields": {
          "my_field": [
            true                  <-- note this
          ]
        }
      }
    ]

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 data type instead of the object data type.

You can use the script as shown in my another answer if you want to just compare the value of the first element of the array to some other value. But based on your comments, it looks like your use case is quite different.

If you want to search the first element of the array you need to convert your data, into nested form. Using arrays of object at search time you can’t refer to “the first element” or “the last element”.

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

Index Mapping:

{
  "mappings": {
    "properties": {
      "name": {
        "type": "nested"
      }
    }
  }
}

Index Data:

{
  "booking_id": 2,
  "name": [
    {
      "first": "John Doe",
      "second": "abc"
    }
  ]
}
{
  "booking_id": 1,
  "name": [
    {
      "first": "Adam Simith",
      "second": "John Doe"
    }
  ]
}
{
  "booking_id": 3,
  "name": [
    {
      "first": "John Doe",
      "second": "Adam Simith"
    }
  ]
}

Search Query:

{
  "query": {
    "nested": {
      "path": "name",
      "query": {
        "bool": {
          "must": [
            {
              "match_phrase": {
                "name.first": "John Doe"
              }
            }
          ]
        }
      }
    }
  }
}

Search Result:

"hits": [
      {
        "_index": "test",
        "_type": "_doc",
        "_id": "2",
        "_score": 0.9400072,
        "_source": {
          "booking_id": 2,
          "name": [
            {
              "first": "John Doe",
              "second": "abc"
            }
          ]
        }
      },
      {
        "_index": "test",
        "_type": "_doc",
        "_id": "3",
        "_score": 0.9400072,
        "_source": {
          "booking_id": 3,
          "name": [
            {
              "first": "John Doe",
              "second": "Adam Simith"
            }
          ]
        }
      }
    ]
Related