Dušan Maďar
Dušan Maďar

Reputation: 9909

Elasticsearch - value in array filter

I want to filter out all documents which contain a specific value in an array field. I.e. the value is an element of that array field.

To be specific - I want to select all documents which names contains test-name, see the example below.


So when I do an empty search with

curl -XGET localhost:9200/test-index/_search

the result is

{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 50,
    "max_score": 1,
    "hits": [
      {
        "_index": "test-index",
        "_type": "test",
        "_id": "34873ae4-f394-42ec-b2fc-41736e053c69",
        "_score": 1,
        "_source": {
          "names": [
            "test-name"
          ],
          "age": 100,
          ...
        }
      },
      ...
   }
}


But in case of a more specific query

curl -XPOST localhost:9200/test-index/_search -d '{
  "query": {
    "bool": {
      "must": {
        "match_all": {}

      },
      "filter": {
        "term": {
           "names": "test-name"
        }
      }
    }
  }
}'

I don't get any results

{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 0,
    "max_score": null,
    "hits": []
  }
}


There are some questions similar to this one. Although, I cannot get any of the answers to work for me.

System specs: Elasticsearch 5.1.1, Ubuntu 16.04


EDIT

curl -XGET localhost:9200/test-index
          ...
          "names": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          ...

Upvotes: 2

Views: 8770

Answers (1)

Val
Val

Reputation: 217554

That's because the names field is analyzed and test name gets indexed as two tokens test and name.

Searching for the test name term will hence not yield anything. If you use match instead, you'll get the document.

If you want to check for the exact value test name (i.e. the two tokens one after another), then you need to change your names field to a keyword type instead of text

UPDATE

According to your mapping, the names field is analyzed, you need to use the names.keyword field instead and it will work, like this:

curl -XPOST localhost:9200/test-index/_search -d '{
  "query": {
    "bool": {
      "must": {
        "match_all": {}

      },
      "filter": {
        "term": {
           "names.keyword": "test-name"
        }
      }
    }
  }
}'

Upvotes: 4

Related Questions