Если главное - скорость поиска, то можно проиндексировать с помощью N-gram фильтра:
DELETE test_index
PUT test_index
{
"settings": {
"analysis": {
"filter": {
"ru_stop": {
"type": "stop",
"stopwords": "_russian_"
},
"ru_stem": {
"type": "stemmer",
"language": "russian"
},
"en_stem": {
"type": "stemmer",
"language": "english"
},
"en_pos": {
"type": "stemmer",
"language": "possessive_english"
},
"ngram": {
"type": "edgeNGram",
"min_gram": 1,
"max_gram": 20
}
},
"analyzer": {
"my_stemmer": {
"type": "custom",
"tokenizer": "standard",
"filter": ["lowercase", "ru_stop", "ru_stem", "en_pos"]
},
"my_ngram_index": {
"type": "custom",
"tokenizer": "standard",
"filter": ["lowercase", "ru_stop", "ngram"]
},
"my_ngram_search": {
"type": "custom",
"tokenizer": "standard",
"filter": ["lowercase"]
}
}
}
},
"mappings": {
"doc": {
"properties": {
"text": {
"type": "text",
"analyzer": "my_stemmer",
"fields": {
"ngrams": {
"type": "text",
"analyzer": "my_ngram_index",
"search_analyzer": "my_ngram_search"
}
}
}
}
}
}
}
POST /test_index/doc/_bulk?refresh
{ "index" : { "_id" : "1" } }
{ "text" : "Балтика №0, Балтика №1" }
{ "index" : { "_id" : "2" } }
{ "text" : "Lion's Head или Lions" }
GET test_index/doc/_search
{
"query": {
"multi_match": {
"query": "Балтика",
"fields": ["text", "text.ngrams"]
}
}
}
GET test_index/doc/_search
{
"query": {
"multi_match": {
"query": "Балтикой",
"fields": ["text", "text.ngrams"]
}
}
}
GET test_index/doc/_search
{
"query": {
"multi_match": {
"query": "Бал",
"fields": ["text", "text.ngrams"]
}
}
}
GET test_index/doc/_search
{
"query": {
"multi_match": {
"query": "lion",
"fields": ["text", "text.ngrams"]
}
}
}
Если заботить размер индекса и не волнует скорость поиска или требуемая память - то можно искать с помощью match_phrase_prefix
или prefix
.
DELETE test_index
PUT test_index
{
"settings": {
"analysis": {
"filter": {
"ru_stop": {
"type": "stop",
"stopwords": "_russian_"
},
"ru_stem": {
"type": "stemmer",
"language": "russian"
},
"en_stem": {
"type": "stemmer",
"language": "english"
},
"en_pos": {
"type": "stemmer",
"language": "possessive_english"
}
},
"analyzer": {
"my_stemmer": {
"type": "custom",
"tokenizer": "standard",
"filter": ["lowercase", "ru_stop", "ru_stem", "en_pos"]
}
}
}
},
"mappings": {
"doc": {
"properties": {
"text": {
"type": "text",
"analyzer": "my_stemmer",
"fields": {
"standard": {
"type": "text",
"analyzer": "standard"
}
}
}
}
}
}
}
POST /test_index/doc/_bulk?refresh
{ "index" : { "_id" : "1" } }
{ "text" : "Балтика №0, Балтика №1" }
{ "index" : { "_id" : "2" } }
{ "text" : "Lion's Head или Lions" }
GET test_index/doc/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"text": "Бал"
}
},
{
"match_phrase_prefix": {
"text.standard": "Бал"
}
}
]
}
}
}