@ordinary_pavel

Как организовать автокомплит адреса в Elasticsearch?

Доброго времени суток! Возникла необходимость в написании автокомплита адресов. Для этого решили брать адреса из БД ФИАСа и индексировать в еластике в виде строки адреса типа "Магаданская область, г. Магадан, ул Пролетарская, д. 117".
По этой строке я делаю полнотекстовый поиск.
Анализатор кастомный. Настройки следующие:
https://gist.github.com/anonymous/dc84e31ff7f40ea3...

Для запросов использую match_phrase_prefix:
'match_phrase_prefix': {
"plaintext": {
"query": "ленина 7",
"analyzer": "address"
}

}

Ищет более-менее вменяемо. Однако, есть две проблемы.
1) как бы мне не учитывать порядок слов, по которым происходит поиск в фразе? Есть ли варианты кроме slop?
2) При поиске по префиксам когда делаешь запрос вида: "Ленина 1" результаты "Ленина д. 1", "Ленина д. 12", "Ленина д. 113" и т.п. имеют одинковый score в выдаче (предполагаю, что еластик побайтово анализирует строку при поиске по префиксу и как только находит совпадение по некоторому токену включает результат в выдачу независимо от того, то идет за совпадением). Соответственно, возникает неприятная ситуация, когда по запросу "Ленина 1" первый дом получить невозможно (при ограничении числа результатов 10), т.к. выдачу засоряют дома вроде "Ленина д. 112", "Ленина д. 113").
Как бы мне дать бонус для точного совпадения?

Пробовал также suggest поле, но искало не очень хорошо, в виду того что по inputу нельзя сделать нормальный query
Ну и вообще возможно идея организации автокомплита полнотекствым поиском не лучшая. Есть ли у кого то идеи как правильно делать автокомплит адреса?
  • Вопрос задан
  • 1436 просмотров
Пригласить эксперта
Ответы на вопрос 1
chupasaurus
@chupasaurus
Сею рефлекторное, злое, временное
Натравить analyzer ниже, вписав его в индекс и к нужным полям:
{
  "settings": {
    "analysis": {
      "analyzer": {
        "address_analyzer_toster": {
          "tokenizer": "whitespace",
          "char_filter": [
            "useless_symbols",
          ],
          "filter": "useless_words": {
                    "type":       "stop",
                    "stopwords": ["ул", "д", "проезд", ...]
          }
        }
      },
      "char_filter": {
        "useless_symbols": {
          "type": "pattern_replace",
          "pattern": "[,\.:].*",
          "replacement": ""
        }
      }
    }
  }
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы