Issue
I have a locations index, which has lots of location names and their respective countries.
I then want to know whether we have locations with title "Berlin" in the country with country code "DE".
Here's my Java code attempt:
SearchResponse response = client.prepareSearch("locations")
.setQuery(QueryBuilders.matchQuery("title", "Berlin"))
.setFilter(FilterBuilders.termFilter("country", "DE"))
.execute()
.actionGet();
But this gives me too many replies, e.g. results for "Zoo Berlin" and so on. I need exact matches.
(But please note that I have other scenarios where this substring/text search matching is desired.)
Is there a way to decide at querying time, rather than at indexing time which behaviour (exact vs. analyzed text) one wants?
Solution
Index the field you perform a term filter on as not_analyzed. For example, you can index the "country" field as a multi_field, with one of the sub-fields not_analyzed:
"country": {
"type": "multi_field",
"fields": {
"country": {"type": "string", "index": "analyzed"},
"exact": {"type": "string","index": "not_analyzed"}
}
}
Additionally, you could do the same with the "title" field in order to perform a term query:
"title": {
"type": "multi_field",
"fields": {
"title": {"type": "string", "index": "analyzed"},
"exact": {"type": "string","index": "not_analyzed"}
}
}
Then at query time, if you want a title with the exact term "Berlin" filtered by the exact term "DE", use a term query and term filter with the not_analyzed fields:
SearchResponse response = client.prepareSearch("locations")
.setQuery(QueryBuilders.termQuery("title.exact", "Berlin"))
.setFilter(FilterBuilders.termFilter("country.exact", "DE"))
.execute()
.actionGet();
Note that term filters and term queries require not_analyzed fields to work (i.e., to return exact matches).
Answered By - Scott Rice
Answer Checked By - Willingham (JavaFixing Volunteer)