#elasticsearch
#elasticsearch
Вопрос:
У меня есть строка поиска Resta
, и в настоящее время мои результаты включают:
"Save at any restaurant!",
"Save at any gas station!"
Причина в моем индексе:
{
"rewards": {
"aliases": {},
"mappings": {
"_doc": {
"properties": {
"name": {
"type": "text",
"fields": {
"name": {
"type": "text",
"analyzer": "ngram_analyzer"
}
}
},
}
}
},
"settings": {
"index": {
"number_of_shards": "5",
"provided_name": "rewards",
"creation_date": "1555542654894",
"analysis": {
"filter": {
"ngram_filter": {
"type": "ngram",
"min_gram": "2",
"max_gram": "20"
}
},
"analyzer": {
"ngram_analyzer": {
"filter": [
"lowercase",
"ngram_filter"
],
"type": "custom",
"tokenizer": "standard"
}
}
},
"number_of_replicas": "1",
"uuid": "Nzf6KNHkQIeKP0HbVFK1lw",
"version": {
"created": "6060299"
}
}
}
}
}
когда я смотрю на документ с Save at any gas station!
достаточной уверенностью, я вижу sta
его как ngram.
{
"_index": "rewards",
"_type": "_doc",
"_id": "6",
"_version": 1,
"found": true,
"took": 0,
"term_vectors": {
"name": {
"field_statistics": {
"sum_doc_freq": 73,
"doc_count": 3,
"sum_ttf": 73
},
"terms": {
"any": {
"term_freq": 1,
"tokens": [
{
"position": 2,
"start_offset": 8,
"end_offset": 11
}
]
},
"save": {
"term_freq": 1,
"tokens": [
{
"position": 0,
"start_offset": 0,
"end_offset": 4
}
]
},
"sta": {
"term_freq": 1,
"tokens": [
{
"position": 4,
"start_offset": 16,
"end_offset": 23
}
]
},
}
}
}
}
(Я опустил многие другие для краткости)
Используемый запрос:
{
"bool": {
"should": [
{
"multi_match": {
"query": "restaurant",
"fields": [
"name",
"category",
],
"operator": "and"
}
}
]
}
}
Когда я ищу, я получаю результат
["Save at any restaurant!", 1.1967528]
["Save at any gas station!", 0.7141209]
Пользователь здесь на самом деле ищет Restaurant
, и мне интересно, как фильтровать или исключать результаты по баллам. Кажется, я не могу найти хорошее определение оценки (оно кажется относительным), но как мне не показывать Save at any gas station!
здесь (в конечном итоге).
Даже если указать полную поисковую фразу restaurant
, результаты будут только немного лучше:
["Save at any restaurant!", 1.253743]
["Save at any gas station!", 0.7141209]
Комментарии:
1. Можете ли вы также поделиться своим запросом?? Вы можете выбрать использование анализатора времени поиска, отличного от ngrams. Он будет соответствовать resta тому, что у вас есть в вашем индексе, поскольку вы используете размер 2-20 ngram, это будет соответствовать только ресторану
2. @ByronVoorbach это может быть то, что мне нужно, я обновил свой ответ с помощью запроса. Дайте мне знать, если это поможет
3. Да, настройте другой поисковый анализатор для запроса (который не использует ngrams), и все готово! Более стабильные результаты более высокая производительность: D
Ответ №1:
Вы можете просто создать анализатор Edge-Ngram в сопоставлении и использовать его только и только в поисковом запросе.
Что делает edge ngram, так это то, что он создает только нижеприведенные токены, используя начальные буквы слова.
Например, re, res, rest, resta, restau, restaur, restaura, restauran, restaurant
Я добавил анализатор edge n-gram и заметил, что я не использую этот анализатор ни в одном из полей. Я бы использовал этот анализатор только во время поискового запроса.
Это означает, что он будет искать только вышеупомянутые токены restaurant в инвертированном индексе.
Ниже приведен пример сопоставления и его запрос.
Отображение
PUT <your_index_name>
{
"mappings":{
"mydocs":{
"properties":{
"name":{
"type":"text",
"fields":{
"name":{
"type":"text",
"analyzer":"ngram_analyzer"
}
}
}
}
}
},
"settings":{
"index":{
"number_of_shards":"5",
"analysis":{
"filter":{
"ngram_filter":{
"type":"ngram",
"min_gram":"2",
"max_gram":"20"
},
"edgengram_filter":{
"type":"edge_ngram",
"min_gram":"2",
"max_gram":"20"
}
},
"analyzer":{
"ngram_analyzer":{
"filter":[
"lowercase",
"ngram_filter"
],
"type":"custom",
"tokenizer":"standard"
},
"edgengram_analyzer":{
"filter":[
"lowercase",
"edgengram_filter"
],
"type":"custom",
"tokenizer":"standard"
}
}
},
"number_of_replicas":"1"
}
}
}
Ниже приведен ваш запрос:
Запрос
POST <your_index_name>/_search
{
"query":{
"bool":{
"should":[
{
"multi_match":{
"query":"restaurant",
"fields":[
"name",
"category"
],
"operator":"and",
"analyzer":"edgengram_analyzer" <---- Added this
}
}
]
}
}
}
Вы сможете увидеть требуемый результат.
Надеюсь, это поможет.
Комментарии:
1. это правильный ответ, но полезные нагрузки, похоже, не работают, мне пришлось немного подправить, можете ли вы обновить, и я приму?
"illegal_argument_exception","reason":"Unknown filter type [edgengram_filter] for [edgengram_filter]"}]
2. @Anthony, я добавил сопоставление, которое работало в моей версии ES 5.5.2. Пожалуйста, проверьте и дайте мне знать.