#elasticsearch
#elasticsearch
Вопрос:
У меня есть индекс поиска для продуктов, и некоторые из продуктов имеют формат, подобный so:
product1-mk1
product1-mk2
product1-mk3
product2-mk1
...
Очевидно, что эластичный поиск может очень хорошо соответствовать, если кто-то ищет, используя точную фазу product1-mk1
но если пользователь использует пробел вместо дефиса product1 mk1
, результаты поиска кажутся дикими, и «продукт-mk1» найден, но он находится довольно далеко внизу результатов.
Могу ли я что-нибудь сделать в своих сопоставлениях, чтобы учесть это? Мои сопоставления выглядят следующим образом:
'mappings' => [
'products' => [
'name' => [
'type' => 'text',
'include_in_all' => true,
'search_analyzer' => 'standard'
],
Мои настройки индекса такие:
'settings' => [
'analysis' => [
'filter' => [
'ngram_filter' => [
"type" => "edge_ngram",
"min_gram" => 2,
"max_gram" => 6
]
],
'analyzer' => [
'ngram_analyzer' => [
"type" => "custom",
"tokenizer" => "word_split",
"filter" => [
"lowercase",
"ngram_filter"
]
]
],
'tokenizer' => [
'word_split' => [
'type' => 'ngram',
'min_gram' => 2,
'max_gram' => 6,
'token_chars' => [
'letter',
'digit',
'punctuation',
'symbol'
]
]
]
]
],
Если бы кто-нибудь мог указать мне правильное направление, это было бы очень ценно, я предполагаю, что мне не хватает правильной терминологии для решения этой проблемы.
Ответ №1:
Вы можете использовать .keyword
поле, если используете динамическое сопоставление для своего индекса, или создать поле ключевого слова, а затем использовать запрос bool с предложением should для text
и keyword
для получения ожидаемых результатов.
Рабочий пример использования динамического сопоставления, которое создает .keyword
поле для каждого текстового поля.
Примеры документов для индексирования
{
"product" : "product1-mk1"
}
{
"product" : "product1-mk2"
}
{
"product" : "product1-mk3"
}
Поисковый запрос с пробелами
{
"query": {
"bool": {
"should": [
{
"match": {
"product": "product1 mk1"
}
},
{
"match": {
"product.keyword": "product1 mk1"
}
}
]
}
}
}
Результаты поиска, вы можете заметить, что первый результат имеет в ~ 10 раз лучший результат
hits": [
{
"_index": "hyphen",
"_type": "_doc",
"_id": "1",
"_score": 1.1143606,
"_source": {
"product": "product1-mk1"
}
},
{
"_index": "hyphen",
"_type": "_doc",
"_id": "2",
"_score": 0.13353139,
"_source": {
"product": "product1-mk2"
}
},
{
"_index": "hyphen",
"_type": "_doc",
"_id": "3",
"_score": 0.13353139,
"_source": {
"product": "product1-mk3"
}
}
]
Ответ №2:
я недавно столкнулся с этим, вам нужен пользовательский анализатор, пользовательский сопоставитель фильтров символов и пользовательский анализатор поиска:
"analyzer": {
"ngram_index_analyzer": {
"tokenizer": "keyword",
"type": "custom",
"char_filter": [
"ngram_mappings_char_filter"
],
"filter": [
"lowercase",
"trim",
"ngram_filter"
]
},
"ngram_search_analyzer": {
"tokenizer": "keyword",
"char_filter": [
"ngram_mappings_char_filter"
],
"filter": [
"trim"
]
}
},
"char_filter": {
"ngram_mappings_char_filter": {
"type": "mapping",
"mappings" : ["-=>_"]
}
},
"filter": {
"ngram_filter": {
"type": "ngram",
"min_gram": 1,
"max_gram": 10
}
}
для пробелов вы можете добавить еще одно сопоставление фильтра символов