Как вывести несколько товаров из разных категорий на Elasticsearch?
Привет,
есть интернет-магазин с ~1000 поставщиков. У каждого может быть от 100 до 10000 товаров.
Поиск на сайте делаю через Elasticsearch 5.1.1. Индексы примерно следующие:
suppliers:
- title
goods:
- supplier_id
- title
Подключил русскую морфологию, все работает шикарно. Но проблема в том, что из-за обилия товаров у каждого поставщика, один поставщик в результатах выдачи может занимать несколько первых страниц.
Учитывая, что дальше первой страницы вообще мало кто ходит, получается, что конкретные поставщики получают преимущество. Хотелось бы этого избежать.
Я могу сделать случайную сортировку, основанную на сесии, но релевантность из-за этого сбивается и по запросу "детская одежда" в конец могут уйти детские товары, а вверх поднимется просто одежда.
В идеале я хочу сделать чередование поставщиков в выдаче с сохранением релевантности.
Сейчас:
- Товар из поставщика 1
- Товар из поставщика 1
- Товар из поставщика 1
- Товар из поставщика 1
- Товар из поставщика 2
- Товар из поставщика 2
- Товар из поставщика 2
- Товар из поставщика 2
А нужно:
- Товар из поставщика 1
- Товар из поставщика 2
- Товар из поставщика 1
- Товар из поставщика 2
- Товар из поставщика 3
- Товар из поставщика 4
....
Можно получить полностью результат поиска и рассортировать его на PHP, но это как-то по варварски. Уверен, что должны быть способы сделать это через эластик. Может кто-то сталкивался и подскажет?
Поясню, что названия товаров могут быть абсолютно идентичными, вроде "Носки детские". И таких штук 50, например. По запросу "детские носки" они окажутся на первых страницах, но ведь носков полно и у других поставщиков.
Вам должны подойти аггрегированные запросы типа "Top hits Aggregation".
Смысл в том, что вы в таком запросе указываете поле, по которому нужно сгруппировать данные (в вашем случае поле поставщика) и можно задать кол-во документов для каждой такой группировки, напр. 2-3 (будет зависеть от кол-во выводимых вами результатов на странице).
В результате такого запроса вы получите топовые 2-3 результата по каждому поставщику и уже методами PHP можно рандомно их перемешать и выдать пользователю.
Похоже, но чуть-чуть не то. В этом случае мне после агрегации нужно делать доп.запросы, либо сразу получать все рзультаты поиска. А в таком случае мне проще просто сделать сортировку на PHP :)
В результате вы получаете 10 "buckets" (поставщиков), каждый из которых содержит 10 самых релевантных документов.
10 и 10 здесь на случай если будет найден только один поставщик и тогда придется вывести на странице 10 записей только по этому поставщику. Если же будут найдено 10 поставщиков, то берете из каждого bucket'a первый документ.