В Elasticsearch получить ранжирование значение поля по уникальным записям.
Индекс содержит записи о прыжках спортсменов. Попыток у одного спортсмена может быть множество.
Структура документа:
{
'event_at' : '2015-01-01T12:12:10', - дата прыжка
'user_id' : 2142, - id спортсмена
'distance' : 4 - результат
}
Необходимо получить выборку:
{
'distance_range' : {
'*-5' : 12, - кол-во уникальных спортсменов у которых максимальный прыжок от 0 до 5.
'6-10' : 14, - кол-во уникальных спортсменов у которых максимальный прыжок от 6 до 10.
'11-15' : 5 - кол-во уникальных спортсменов у которых максимальный прыжок от 10 до 15.
}
}
Пока у меня получалось только получить максимальный результат для каждого спортсмена, но я не могу понять как его можно ранжировать уровнем выше.
Для примера на SQL это могло бы выглядеть так:
SELECT `distace_range`, count(*) FROM (
SELECT
`user_id`,
IF(MAX(`distace`) <=5,
'*-5',
IF(MAX(`distace`) >= 6 AND MAX(`distace`) >= 10,
'6-10',
'11-15'
)
) `distace_range`
FROM `events`
GROUP BY `user_id`
) t
GROUP BY `distace_range;
Ответ
Опубликовал вопрос на официальном форуме elasticsearch.
На данный момент задачу такой выборки не решить штатными средствами для версии elasticsearch 2.1.х т.к. для запроса:
'aggregations' => [
'distance_range' => [
'terms' => [
'field' => 'doc.user_id',
],
'aggregations' => [
'max_distance' => [
'max' => [
'field' => 'doc.distance'
]
]
]
]
]
то не хватает Pipeline агрегатора по range или term
Есть несколько подходов для решения в текущей ситуации:
создание дополнительного индекса содержащего максимальный результат
использование скриптов
просуммировать результат на клиенте
В данный момент я воспользовался 3 вариантом.
Вариант 1 меня не устроил тем, что дополнительный индекс необходимо контролировать, что-бы он был актуален.
Вариант 2 сложность вычисления или влияние на выборку очень сильно влияет на время выборки и дополнительно придется поддерживать код в нескольких системах.
Комментариев нет:
Отправить комментарий