How to search for a part of a word with ElasticSearch
I'm using nGram, too. I use standard tokenizer and nGram just as a filter. Here is my setup:
{
"index": {
"index": "my_idx",
"type": "my_type",
"analysis": {
"index_analyzer": {
"my_index_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"mynGram"
]
}
},
"search_analyzer": {
"my_search_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"standard",
"lowercase",
"mynGram"
]
}
},
"filter": {
"mynGram": {
"type": "nGram",
"min_gram": 2,
"max_gram": 50
}
}
}
}
}
Let's you find word parts up to 50 letters. Adjust the max_gram as you need. In german words can get really big, so I set it to a high value.
Searching with leading and trailing wildcards is going to be extremely slow on a large index. If you want to be able to search by word prefix, remove leading wildcard. If you really need to find a substring in a middle of a word, you would be better of using ngram tokenizer.
I think there's no need to change any mapping. Try to use query_string, it's perfect. All scenarios will work with default standard analyzer:
We have data:
{"_id" : "1","name" : "John Doeman","function" : "Janitor"}
{"_id" : "2","name" : "Jane Doewoman","function" : "Teacher"}
Scenario 1:
{"query": {
"query_string" : {"default_field" : "name", "query" : "*Doe*"}
} }
Response:
{"_id" : "1","name" : "John Doeman","function" : "Janitor"}
{"_id" : "2","name" : "Jane Doewoman","function" : "Teacher"}
Scenario 2:
{"query": {
"query_string" : {"default_field" : "name", "query" : "*Jan*"}
} }
Response:
{"_id" : "1","name" : "John Doeman","function" : "Janitor"}
Scenario 3:
{"query": {
"query_string" : {"default_field" : "name", "query" : "*oh* *oe*"}
} }
Response:
{"_id" : "1","name" : "John Doeman","function" : "Janitor"}
{"_id" : "2","name" : "Jane Doewoman","function" : "Teacher"}
EDIT - Same implementation with spring data elastic search https://stackoverflow.com/a/43579948/2357869
One more explanation how query_string is better than others https://stackoverflow.com/a/43321606/2357869
without changing your index mappings you could do a simple prefix query that will do partial searches like you are hoping for
ie.
{
"query": {
"prefix" : { "name" : "Doe" }
}
}
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-prefix-query.html