У меня есть данные для SKU с некоторыми метаданными, такими как страна, марка, продавец и их ежедневные цены с ежедневными многораздельными индексами.
Мне нужно выполнить запрос, который выполняет следующее:
- Может фильтровать данные о моих ценах по различным критериям, таким как страны, бренды, розничные продавцы, диапазоны цен по двум точным датам.
- Рассчитать среднюю цену в пределах сегмента (может быть страна, бренд, продавец)в моем случае это страна) для обеих дат
- Рассчитать медианный рост цен в этом сегменте между этими датами
- Сортировать по возрастанию в порядке убывания и выбрать
{x}
строк
Вот что у меня сейчас есть:
Шаблон указателя.Я использую типы keyword
вместе с eager_global_ordinals
, установленным в значение true, поскольку я никогда не выполняю запросы диапазона в этих полях, агрегируя их, и мои запросы в основном сосредоточены на чтениях, а не на записях.В большинстве случаев данные индекса времени будут записываться один раз за дату и почти никогда не обновляться (очень мало случаев)
PUT _template/prices
{
"index_patterns": [
"prices-*"
],
"mappings": {
"properties": {
"date": {
"type": "keyword"
},
"skuId": {
"type": "keyword",
"eager_global_ordinals": true
},
"countryId": {
"type": "keyword",
"eager_global_ordinals": true
},
"brandId": {
"type": "keyword",
"eager_global_ordinals": true
},
"retailerId": {
"type": "keyword",
"eager_global_ordinals": true
},
"price": {
"type": "scaled_float",
"scaling_factor": 100
}
}
}
}
Это некоторые фиктивные данные:
PUT prices-20190101/_doc/1
{
"date": "20190101",
"skuId": 1,
"countryId": 1,
"brandId": 1,
"retailerId": 1,
"price": 97123
}
PUT prices-20190101/_doc/2
{
"date": "20190101",
"skuId": 2,
"countryId": 2,
"brandId": 1,
"retailerId": 2,
"price": 12309
}
PUT prices-20190101/_doc/3
{
"date": "20190101",
"skuId": 3,
"countryId": 3,
"brandId": 2,
"retailerId": 2,
"price": 618123
}
PUT prices-20190102/_doc/1
{
"date": "20190102",
"skuId": 1,
"countryId": 1,
"brandId": 1,
"retailerId": 1,
"price": 681123
}
PUT prices-20190102/_doc/2
{
"date": "20190102",
"skuId": 2,
"countryId": 2,
"brandId": 1,
"retailerId": 2,
"price": 124123
}
PUT prices-20190102/_doc/3
{
"date": "20190102",
"skuId": 3,
"countryId": 3,
"brandId": 2,
"retailerId": 2,
"price": 1612.23
}
И фактический запрос квычислить все.
GET /prices-20190101,prices-20190102/_search
{
"size": 0,
"aggs": {
"countryIds": {
"terms": {
"field": "countryId",
"size": 10
},
"aggs": {
"d1": {
"filter": {
"term": {
"date": "20190101"
}
},
"aggs": {
"median": {
"percentiles": {
"field": "price",
"percents": 50
}
}
}
},
"d2": {
"filter": {
"term": {
"date": "20190102"
}
},
"aggs": {
"median": {
"percentiles": {
"field": "price",
"percents": 50
}
}
}
},
"growth": {
"bucket_script": {
"buckets_path": {
"d1median": "d1>median[50.0]",
"d2median": "d2>median[50.0]"
},
"script": "(params.d2median / params.d1median - 1) * 100"
}
},
"growthsort": {
"bucket_sort": {
"sort": [
{
"growth": {
"order": "desc"
}
}
],
"size": 3
}
}
}
}
}
}
Это ответ на запрос выше:
{
"took": 165,
"timed_out": false,
"_shards": {
"total": 2,
"successful": 2,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 6,
"relation": "eq"
},
"max_score": null,
"hits": []
},
"aggregations": {
"countryIds": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "2",
"doc_count": 2,
"d1": {
"doc_count": 1,
"median": {
"values": {
"50.0": 12309.0
}
}
},
"d2": {
"doc_count": 1,
"median": {
"values": {
"50.0": 124123.0
}
}
},
"growth": {
"value": 908.3922333252092
}
},
{
"key": "1",
"doc_count": 2,
"d1": {
"doc_count": 1,
"median": {
"values": {
"50.0": 97123.0
}
}
},
"d2": {
"doc_count": 1,
"median": {
"values": {
"50.0": 681123.0
}
}
},
"growth": {
"value": 601.2993832562832
}
},
{
"key": "3",
"doc_count": 2,
"d1": {
"doc_count": 1,
"median": {
"values": {
"50.0": 618123.0
}
}
},
"d2": {
"doc_count": 1,
"median": {
"values": {
"50.0": 1612.23
}
}
},
"growth": {
"value": -99.7391732713392
}
}
]
}
}
}
Это все работает, но я ищу способы улучшить производительность запроса, переписав его по-другому.У меня очень мало опыта работы с агрегацией конвейеров, и я надеюсь, что это можно сделать более эффективно.
Этот запрос будет работать с 20M SKU на производстве, поэтому около 40M документов (20M SKU * 2 дня)