Я хочу использовать Elasticsearch для повышения производительности при поиске товаров (duh) в решении для электронной коммерции.У нас есть модель данных, в которой продукт может иметь несколько вариантов, и у каждого варианта может быть одна или несколько цен (иногда довольно значительное количество цен).
Пользователь, запрашивающий время, выбирает, если онхочет вернуть продукты или варианты, и должна быть возвращена только одна цена (самая низкая действительная цена, каждая цена имеет несколько полей, например, действительные от-до и действительные группы клиентов).
Мой первый подход состоял в денормализации продукта/ варианты и имеют цены как вложенные поля, но это было довольно медленно, и у меня было несколько проблем с сортировкой (я думаю о цене, но точные детали ускользают от меня прямо сейчас).
Второй подход заключался в полной денормализации, поэтому вся комбинация продукт / вариант / цена представляется в виде документа.Этот подход намного быстрее (очевидно), я могу агрегировать по productId
или variantId
и получать самую низкую цену, но проблема в том, что я не могу отсортировать агрегаты по нечисловым или неагрегированным полям.
Денормализованные документы (productId
, variantId
- поля ключевых слов, price
- числовые, validFrom
/ - To
- даты, а остальные текстовые):
[
{
"productId": "111-222-333",
"variantId": "aaa-bbb-ccc",
"product_title": "Mega-product",
"product_description": "This awesome piece of magic will change your life",
"variant_title": "Green mega-product",
"variant_description": "Behold the awesomeness of the green magic mega-product",
"color": [
"blue",
"green"
],
"brand": "DaBrand",
"validFrom": "2019-06-01T00:00:00Z",
"validTo": null,
"price": 399
},
{
"productId": "111-222-333",
"variantId": "aaa-bbb-ddd",
"product_title": "Mega-product",
"product_description": "This awesome piece of magic will change your life",
"variant_title": "Blue mega-product",
"variant_description": "Behold the awesomeness of the blue magic mega-product",
"color": [
"blue",
"green"
],
"brand": "DaBrand",
"validFrom": "2019-06-01T00:00:00Z",
"validTo": null,
"price": 499
},
{
"productId": "111-222-333",
"variantId": "aaa-bbb-ddd",
"product_title": "Mega-product",
"product_description": "This awesome piece of magic will change your life",
"variant_title": "Blue mega-product",
"variant_description": "Behold the awesomeness of the blue magic mega-product",
"color": [
"blue",
"green"
],
"brand": "DaBrand",
"validFrom": "2019-06-05T00:00:00Z",
"validTo": "2019-06-10T00:00:00Z",
"price": 399
}
]
Примеррабочий запрос, где я сортирую по агрегированной цене.
{
"size": 1,
"sort": {
"product_name_text_en.keyword": "asc"
},
"query": {
// All the query and filtering
},
"aggs": {
"by_product_id": {
"terms": {
"field": "product_id_string",
"order": {
"min_price": "desc"
}
},
"aggs": {
"min_price": {
"min": {
"field": "price_decimal"
}
}
}
}
}
}
Однако, используя этот подход, я не могу найти способ сортировки по полям документа.Это возможно (я думаю) для числовых, логических полей и полей даты, используя bucket_sort
, но мне нужно иметь возможность сортировать, например, поле бренда или заголовка (которые являются текстовыми).Если бы было возможно order
при агрегации top_hits, я был бы дома свободен, но, к сожалению, это невозможно, как я понял из документации (я также попробовал это просто, чтобы убедиться).
Может кто-нибудь направить меня к лучшему решению?Я не возражаю, если мне придется выполнить запрос в два этапа, но для того, чтобы это работало для сортировки, мне, вероятно, нужно иметь несколько разных «типов документов», таких как Product, Variant, ProductPrice и VariantPrice для использования в зависимости от запрошенногоПорядок сортировки.Я далеко не так далеко, так что окончательное ремоделирование находится на столе, я рассмотрел использование полей соединения, но я не уверен, что это будет эффективным.
Так как количество продуктов и вариантов (и цен) может быть значительным - миллион продуктов определенно находится на столе, я думаю, что у меня будут проблемы с получением идентификаторов из запроса (например, фильтрация по бренду и сортировка поtitle), а затем отправьте их в запрос на получение наилучшей цены.