- PVSM.RU - https://www.pvsm.ru -
Вопрос умной категоризации чего-либо встаёт остро при разработке очень многих сайтов. Конечно, всегда можно отдать это на заполнение человеку и результат поначалу будет куда лучше машинного, но, что если категоризировать нужно в реальном времени сотни и тысячи «товаров».
Придется отдать это на откуп машине. Тут вариантов не так много, а написание собственного ИИ для 99.9% задач пустая трата времени.
Заинтересовавшимся как это решить с помощью ElasticSearch прошу под кат.
Если вы еще не знакомы с ElastiSearch, то советую прекрасную статью «Быстрый полнотекстовый поиск ElasticSearch» [1] от пользователя brujeo [2]
В SmartProgress [3] мы реализовали категоризацию в виде групп, которые объединяют цели пользователей в общие группы по интересам. Но как соотнести эти группы (которых уже более 100) с пользовательской целью так, чтобы ему на выбор было предложено максимум 3 группы и при этом они были максимально релевантные цели?
Простейшим вариантом было бы использовать, например, теги для привязки к той или иной группе, но в реальности это работает не так хорошо, как хотелось бы, плюс заставлять тех же пользователей заполнять теги может быть оправдано только для IT сферы.
Предположим, что у нас есть категория «Программирование на Ruby on Rails», тогда поисковый запрос по правилам simple query string [4] будет выглядеть примерно так:
Ruby | RoR | "Ruby on Rails" | "программирование Ruby"~4 | "вставать на рельсы" -php -java -net
Немного поясню запрос: | — или, "..." — вхождения всего словосочетания, ~N — возможно разбавка словосочетания N словами
Если нужно найти все «товары»(в нашем случае цели), которые подходят под такой запрос, то достаточно просто выполнить поиск. А если надо найти все категории под определённый товар? Тут приходит на помощь Percolate API [5]
Признаюсь честно, моё знакомство с ElasticS началось именно с этой «фишки», до этого я работал только со сфинксом, но он не умеет делать обратный поиск.
Поэтому, прочитав документацию, я толком не понял что это такое и как с этим работать, а информации в гугле, особенно по версии >1.X, было крайне мало. Но упорство победило (на >5 странице гугла есть жизнь).
Я попробую объяснить на пальцах как это работает:
Давайте попробуем это в действии:
— Создаём индекс «test» (без mapping, он нам не понадобится)
curl -XPUT 'http://localhost:9200/test'
— Создаём .percolator
curl -XPUT 'http://localhost:9200/test/.percolator/simple-search' -d '
{
"query" : {
"simple_query_string" : {
"query" : "Ruby | RoR | "Ruby on Rails" | "программирование Ruby"~4 | "вставать на рельсы" -php -java -net",
"analyzer" : "simple",
"fields" : ["name^5", "description"],
"default_operator" : "and"
}
},
"language" : "ru",
}'
Подробнее:
test — Индекс
.percolator — Тип
simple-search — ID (может быть как int так и string)
"query"
— поиск
simple_query_string — Функция для поиска. Полный список [6]
"fields" : ["name^5", "description"]
— тут мы указали по каким полям идёт поиск, и указали коэффициент 5 для поля «name», т.к. обычно там самая важная информация. Подробнее [7].
"active" : 1
— Дополнительные параметры, не обязательные, может быть несколько любого типа, применяются в фильтрации результата.
По сути .percolator это такой же объект, как и любой другой в индексе, поэтому к нему также можно применять mapping.
— Ищем:
curl -XPOST 'http://localhost:9200/test/category/_percolate?pretty' -d '
{
"doc" : {
"name" : "Изучить Ruby on Rails максимально быстро",
"description" : "Я хочу программировать на Ruby"
},
"filter" : {
"term" : {
"language" : "ru"
}
}
}'
Ответ:
{
"took" : 5,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"total" : 1,
"matches" : [ {
"_index" : "test",
"_id" : "simply-search"
} ]
}
Совпадений может быть несколько
Этот способ прекрасно подходит, если вы по какой-то причине не хотите переносить всю информацию в ElasticS. Или хотите потестить ваш percolator
Давайте добавим 1 запись в индекс test
curl -XPUT 'http://localhost:9200/test/category/1' -d '
{
"name" : "Изучить Ruby on Rails максимально быстро",
"description" : "Я хочу программировать на Ruby"
}'
И посмотри к каким категориям эта запись подходит:
curl -XGET 'http://localhost:9200/test/category/1/_percolate?pretty'
Ответ:
{
"took" : 4,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"total" : 1,
"matches" : [ {
"_index" : "test",
"_id" : "simply-search"
} ]
}
Ну, что же, мы смогли сделать «поиск наоборот». Где это можно использовать? Применений море, от хитрых выборок до напоминалок по событию, всё ограничивается только вашей фантазией и оперативной памятью.
К сожалению не всё так замечательно, как выглядит со стороны. Да, это работает, но есть минусы:
Да, они поддерживают репликацию, как любой объект ElasticSearch, но тем не менее применять этот механизм нужно крайне осторожно.
Пару простых советов как избежать out of memory:
P.S. Я не являюсь гуру ES, поэтому рад любым замечаниям и дополнениям.
Автор: OneArt
Источник [12]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/php-2/62787
Ссылки в тексте:
[1] «Быстрый полнотекстовый поиск ElasticSearch»: http://habrahabr.ru/post/122531/
[2] brujeo: http://habrahabr.ru/users/brujeo/
[3] SmartProgress: https://smartprogress.do
[4] simple query string: http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-simple-query-string-query.html#_simple_query_string_syntax
[5] Percolate API: http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-percolate.html
[6] Полный список: http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-queries.html
[7] Подробнее: http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-simple-query-string-query.html
[8] macth: http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-match-query.html
[9] bool query: http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html#query-dsl-bool-query
[10] Whats new in percolator: https://speakerdeck.com/javanna/whats-new-in-percolator
[11] DHC — REST HTTP API Client: https://chrome.google.com/webstore/detail/dhc-rest-http-api-client/aejoelaoggembcahagimdiliamlcdmfm?utm_source=plus
[12] Источник: http://habrahabr.ru/post/226749/
Нажмите здесь для печати.