Улучшение запроса кросс-индекса Elasticsearch для расчета среднего роста - PullRequest
0 голосов
/ 28 сентября 2019

У меня есть данные для SKU с некоторыми метаданными, такими как страна, марка, продавец и их ежедневные цены с ежедневными многораздельными индексами.

Мне нужно выполнить запрос, который выполняет следующее:

  1. Может фильтровать данные о моих ценах по различным критериям, таким как страны, бренды, розничные продавцы, диапазоны цен по двум точным датам.
  2. Рассчитать среднюю цену в пределах сегмента (может быть страна, бренд, продавец)в моем случае это страна) для обеих дат
  3. Рассчитать медианный рост цен в этом сегменте между этими датами
  4. Сортировать по возрастанию в порядке убывания и выбрать {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 дня)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...