Reputation: 661
I have consulted few articles and stackoverflow questions but I am afraid I wasn't able to find anything like my scenario, forgive me if its duplicate.
Problem:
I want to match a word "Tennis" to a filed which has an array of sports ["Football", "Tennis", "Table Tennis", "Basketball"]
. Now the word should be an exact match.
Mapping:
"properties": {
"clubname": {
"type": "text"
},
"sports": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
DOC:
// DOC1
{
"clubname": "Arena 51",
"sports: ["Cricket","Football", "Tennis"]
}
// DOC2
{
"clubname": "Play You",
"sports: ["Cricket","Football", "Table Tennis"]
}
Query:
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": [
{
"match": {
"sports": "tennis"
}
}
]
}
}
With this query I get both documents, which I believe is correct behaviour. So how do I make elastic search to return only Doc1
when I search just Tennis
Upvotes: 3
Views: 891
Reputation: 16172
The answer given by @Opster works fine if you search for Tennis
, but if you want to have case insensitive search, you need to create custom normalization for index in the following way:
Index Mapping:
{
"settings": {
"analysis": {
"normalizer": {
"lowercase_normalizer": {
"type": "custom",
"char_filter": [],
"filter": [
"lowercase",
"asciifolding"
]
}
}
}
},
"mappings": {
"properties": {
"sports": {
"type": "keyword",
"normalizer": "lowercase_normalizer"
}
}
}
}
Search query:
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": [
{
"match": {
"sports": "tennis"
}
}
]
}
}
}
Search Result:
"hits": [
{
"_index": "fd_cb2",
"_type": "_doc",
"_id": "1",
"_score": 1.0,
"_source": {
"clubname": "Arena 51",
"sports": [
"Cricket",
"Football",
"Tennis"
]
}
}
]
Upvotes: 1
Reputation: 7864
For exact match you can use keyword
sub-field:
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": [
{
"term": {
"sports.keyword": "Tennis"
}
}
]
}
}
}
Note that this will be case sensitive.
Upvotes: 1