Exact matches with ElasticSearch (at query time)
elasticsearch, java
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).
Problem
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?