@verberden

Как организовать поиск по названиям продуктов, по части названия?

Привет всем!
В наличии есть БД на Postgres, бэк на Nodejs. До меня пытались прикрутить поиск на Solr, но оказался сложноватым в настройке и с релевантностью было не очень. Я прикрутил elastic и вроде бы стало получше, но все равно неудовлетворительно, а именно:
  • поиск по части слова не работает. то есть введя "греч" - сейчас не находит ничего, так как организован полнотекстовый поиск, а хотелось бы чтобы выдавались результаты с учётом следующих пунктов.
  • необходим поиск вместе с синонимами, то есть введя "гречка", искало бы и "гречневый", "греча" итд с учётом словоформ. Есть, например, "хлебцы с гречей".
  • проблема с ранжированием: хотелось, чтобы если искомое слово(или словоформа) ближе к началу строки(название продукта), то такой результат выше в поиске. Сейчас выходит как-то вперемешку: например, поиск по слову "гречневая"

    602f34a44005d887419019.png

Индекс настроил следующим образом(синонимы это тестовый вариант) и query делаю следующим образом:
esClient.indices.create({
    index: 'products',
    body: {
        "settings": {
            "analysis": {
              "filter": {
                "ru_stop": {
                  "type": "stop",
                  "stopwords": "_russian_"
                },
                "ru_stemmer": {
                  "type": "hunspell",
                  "locale": "ru_RU"
                },
                "synonym": {
                  "type": "synonym",
                  "lenient": true,
                  "synonyms": [ "гречка, гречневая", "греча => гречка"]
                }
              },
              "analyzer": {
                "default": {
                  "tokenizer": "standard",
                  "filter": [
                    "lowercase",
                    "ru_stop",
                    "synonym",
                    "ru_stemmer",
                  ]
                }
              }
            }
        }
    }
})

//QUERY
esClient.search({
    index: "products",
    body: {
        size: 100,
        query: {
            match: {"name": searchText.trim()}
        }
    }
})


Можете подсказать как можно улучшить поиск? Может, другая технология?
  • Вопрос задан
  • 280 просмотров
Пригласить эксперта
Ответы на вопрос 1
ayazer
@ayazer
Sr. Software Engineer
в принципе вариантов несколько тут: solr (который использует lucene), elastic (который использует lucene), lucene (и самому дописать весь функционал который добавляет elastic\solr) и внутренний полнотекстовый поиск в постгреса (когда нужен полнотекстовый поиск, но не настолько чтоб ради него поднимать solr/elastic).

любой с этих вариантов умеет выполнять все пункты что вам нужны (т.е. нечеткий поиск, поиск по синонимам, ранджирование результатов и выставление весов)

поиск по части слова не работает. то есть введя "греч" - сейчас не находит ничего, так как организован полнотекстовый поиск, а хотелось бы чтобы выдавались результаты с учётом следующих пунктов.

перепроверьте как вы запрос составляете. для solr я бы ожидал увидеть поиск по "греч*", для постгреса - поиск по "греч:*"

необходим поиск вместе с синонимами, то есть введя "гречка", искало бы и "гречневый", "греча" итд с учётом словоформ. Есть, например, "хлебцы с гречей".

словари с синонимами настраиваются везде

проблема с ранжированием: хотелось, чтобы если искомое слово(или словоформа) ближе к началу строки(название продукта), то такой результат выше в поиске. Сейчас выходит как-то вперемешку: например, поиск по слову "гречневая"

ну это то, как работает обратный индекс. он ничего не знает про позицию слова, он знает только про факт вхождения слова в результат. в постгресе например я не вижу универсального решения как можно получить такое поведение. Перечитайте документацию про ранжированию/весам, я не удивлюсь если в солр/еластике что-то дописали

UPD: ну и таки да, в комментариях подсказывают что это решается и гуглить документацию по "TF-IDF"
Ответ написан
Ваш ответ на вопрос

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

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