Фильтр по оценке с помощью Ngrams

#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. Пожалуйста, проверьте и дайте мне знать.