Фильтр Elasticsearch по результатам агрегации (для поиска и агрегации) - PullRequest
1 голос
/ 09 октября 2019

Часть этого вопроса связана с: Фильтром Elasticsearch при агрегации

Контекст

Допустим, мой индекс Elasticsearch содержит несколько порядков. Каждый заказ имеет одну цену поля и одну сумму поля. В результате получается индекс, который выглядит следующим образом:

[
  {
    "docKey": "order01",
    "user": "1",
    "price": 8,
    "amount": 20
  },
  {
    "docKey": "order02",
    "user": "1",
    "price": 14,
    "amount": 3
  },
  {
    "docKey": "order03",
    "user": "2",
    "price": 5,
    "amount": 1
  },
  {
    "docKey": "order04",
    "user": "2",
    "price": 10,
    "amount": 3
  }
]

Что я хотел бы сделать

Что я хочу сделать, так это фильтр по некоторым значениям, агрегированным запользователь. Я хочу сделать этот вид фильтра для поиска, а также для того, чтобы применить к нему агрегацию. Например, в этом примере я хотел бы получить документы всех пользователей, у которых есть их средний заказ с ценой в диапазоне 9-14.

Пользователь 1 имеет заказ средней цены 11, поэтому мы сохраняем обаего заказов. У пользователя 2 средний заказ по цене 7,5, поэтому оба его заказа не выполняются.

Это было легко. После того, как я фильтрую, чтобы получить только один пользователь. Я хочу сделать еще несколько агрегатов для результата.

Так, например: я хочу перераспределить среднее значение для каждого пользователя поля amout среди сегментов [0,10] и [10,20] для всехпользователь, у которого средний заказ с ценой в диапазоне 9-14.

Ответ I, за исключением этого вопроса, 0 в корзине [0,10] и один в корзине [10,20](Только пользователь 1 остается из-за его средней цены. Его средняя сумма равна 11,5, поэтому в корзине [10,20]).

То, что я пробовал

Мне удалось сделать фильтр, чтобы получить пользователей, у которых есть их средний заказ с ценой в диапазоне 9-14. Я сделал это, сначала выполнив агрегацию терминов в поле пользователя. Затем я делаю субагрегацию, которая является средней агрегацией по цене. Затем я делаю агрегацию конвейера селектора сегментов, которая проверяет, находится ли предыдущая вычисленная средняя цена между 9 и 14.

Мне также удалось выполнить агрегацию, которую я хотел, но без предыдущего фильтра. Я сделал то же самое, что и для фильтра для каждого диапазона. Затем я подсчитываю количество результатов в каждом сегменте.

Я не нашел способа применить другую агрегацию к результату селектора сегментов. Поэтому я не мог сначала выполнить фильтр, а затем применить диапазон ...

Кроме того, эти решения не изящны ... Я не думаю, что они будут расширяться, поскольку большая часть документа должна быть возвращенав ответе и обрабатываются далее (даже если это не из Интернета, я предпочитаю избегать этого, и я могу быть ограничен в размере агрегации результата?).

1 Ответ

1 голос
/ 10 октября 2019

Мне удается найти решение, но оно не элегантно и может быть плохо масштабируемым.

  • Создайте агрегацию термина для пользователя.
  • В качестве субагрегации терминаагрегация делает среднюю агрегацию, которая вычисляет среднее значение цены.
  • В качестве субагрегации термина агрегация выполняет среднюю агрегацию, которая вычисляет среднее значение суммы.

  • Выполнить агрегацию конвейера селектора сегмента, который фильтрует, чтобы сохранить только avg_price в диапазоне [9-14].

  • Выполнить агрегацию конвейера селектора сегмента, который фильтрует, чтобы сохранить только avg_amount в [0-10]
  • Выполнить агрегацию конвейера сценария "подсчет" (с возвращением скрипта).
  • Выполнить агрегацию конвейера с суммой сегмента, которая суммирует счет.
  • Повтор всехшаги для всех требуемых диапазонов ([0-10], [10-20])
...