0

I am trying to execute a query with a Boolean filter, but it seems like it doesn't work when the type is a string.

Example:

When I send this payload to my _search endpoint:

{
    "query": {
        "filtered": {
            "filter": {
                "bool": {
                    "must": [
                        { "term": { "level" : 3 } },
                        { "term": { "id" : 4 } }
                    ]
                }
            }
        }
    }
}

The result is:

{
  "took": 29,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 1,
    "hits": [
      {
        "_index": "app",
        "_type": "reviewable",
        "_id": "4",
        "_score": 1,
        "_source": {
          "id": 4,
          "name": "Hololens Bootcamp Experience",
          "providers": [],
          "gender": [],
          "duration": "3",
          "category": "COURSE",
          "themes": [],
          "baseThemes": [],
          "budget": "1000+",
          "language": "EN",
          "level": "3",
          "region": "NL_BR",
          "subscribemethod": "2",
          "kind": "2"
        }
      }
    ]
  }
}

Then when I try to filter it with the language term like this:

{
    "query": {
        "filtered": {
            "filter": {
                "bool": {
                    "must": [
                        { "term": { "level" : 3 } },
                        { "term": { "id" : 4 } },
                        { "term": { "language" : "EN" } }
                    ]
                }
            }
        }
    }
}

My result has 0 hits:

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

Which seems weird to me, since you can see in my first result that the filter should match my data.

I have search around, and one post mentioned I might not have everything indexed. But as far as I can find out, I certainly have. Any ideas?

1 Answers1

0

Your language field is most probably an analyzed string, hence EN was tokenized and indexed as en, so your query should be like this instead:

{
    "query": {
        "filtered": {
            "filter": {
                "bool": {
                    "must": [
                        { "term": { "level" : 3 } },
                        { "term": { "id" : 4 } },
                        { "term": { "language" : "en" } }   <--- lowercase here
                    ]
                }
            }
        }
    }
}

Another way to do this is to use a match query instead, but without the wrapping filtered query which is not useful in your case:

{
    "query": {
         "bool": {
             "must": [
                 { "term": { "level" : 3 } },
                 { "term": { "id" : 4 } },
                 { "match": { "language" : "EN" } }
             ]
         }
    }
}
Val
  • 207,596
  • 13
  • 358
  • 360
  • Actually, my actual case requires me to use the query/match construct to find an item with a certrain term in the name field, so I have to rely on the fitler. Your suggest was spot on, because it indeed works when it is lowercase, however, the query gets generate by FosElasticaBundle where the "EN" is the value of an enumeration, so the bundle always tries to filter on "EN" instead of "en". Is there a way to change the analyzer to something that would match "EN"? – Patrick Decoster Oct 17 '16 at 11:54
  • Yes, you simply need to make your `language` field `not_analyzed` in your mapping, i.e. instead of `'language' => array('type' => 'string'),` you need `'language' => array('type' => 'string', 'index' => 'not_analyzed'),` – Val Oct 17 '16 at 11:58