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



@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()}
        }
    }
})

Можете подсказать как можно улучшить поиск? Может, другая технология?


Решения вопроса 0


Ответы на вопрос 1



@ayazer

в принципе вариантов несколько тут: solr (который использует lucene), elastic (который использует lucene), lucene (и самому дописать весь функционал который добавляет elasticsolr) и внутренний полнотекстовый поиск в постгреса (когда нужен полнотекстовый поиск, но не настолько чтоб ради него поднимать solr/elastic).

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

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

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

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

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

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

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

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *