Есть ли какой-нибудь способ получить агрегирование статистики для вложенных полей, чтобы я учитывал только максимум определенных значений вложенных полей для оценки статистики.
Отображение:
{
"mappings": {
"doc": {
"properties": {
"student_id": {
"type": "long"
},
"test_scores": {
"type": "nested",
"properties": {
"test_id": {
"type": "long"
},
"score": {
"type": "double"
}
}
}
}
}
}
}
Пример данных:
{
"student_id": 1,
"test_scores": [
{
"test_id": 101,
"score": 90
},
{
"test_id": 102,
"score": 70
},
{
"test_id": 103,
"score": 80
}
]
}
{
"student_id": 2,
"test_scores": [
{
"test_id": 101,
"score": 80
},
{
"test_id": 102,
"score": 90
},
{
"test_id": 103,
"score": 85
}
]
}
{
"student_id": 3,
"test_scores": [
{
"test_id": 101,
"score": 30
},
{
"test_id": 102,
"score": 40
},
{
"test_id": 103,
"score": 55
}
]
}
Запрос на фильтрацию:
{
"query": {
"bool": {
"should": [
{
"bool": {
"must": [
{
"term": {
"student_id": 1
}
},
{
"nested": {
"path": "test_scores",
"query": {
"terms": {
"test_scores.test_id": [101]
}
}
}
}
]
}
},
{
"bool": {
"must": [
{
"term": {
"student_id": 2
}
},
{
"nested": {
"path": "test_scores",
"query": {
"terms": {
"test_scores.test_id": [101, 103]
}
}
}
}
]
}
}
]
}
}
}
Требования:
Мне нужно найти минимальное и максимальное значения (агрегирование статистики) для test_scores.score для студентов на основе запроса фильтрации aboe, чтобы я учитывал только максимальное значение test_scores.score на каждого студента_id.
Пример:
Из запроса отфильтрованных документов сверху
doc:
student_id: 1
test_scores.test_id: 101
test_scores.score: 90
test_scores.score (To be considered for aggregation): 90
doc:
student_id: 2
test_scores.test_id: 101, 103
test_scores.score: 80, 85
test_scores.score (To be considered for aggregation): 85
Expected overall stats on test_scores.score:
max: 90
min: 85
Результаты
После поиска в сети я нашел решение:
{
"aggs": {
"score_stats": {
"stats": {
"script": "if(doc[\"student_id\"].value == 1){
return params._source[\"test_scores\"]
.stream()
.filter(nested -> nested.test_id == 101)
.mapToDouble(nested -> nested.score)
.max()
.orElse(0)
} else if(doc[\"student_id\"].value == 2){
return params._source[\"test_scores\"]
.stream()
.filter(nested ->
nested.test_id == 101 || nested.test_id == 103)
.mapToDouble(nested -> nested.score)
.max()
.orElse(0)
} else {
return 0
}"
}
}
},
"query": {
//filtering query copied here
}
}
}
Ответ:
"aggregations" : {
"score_stats" : {
"count" : 2,
"min" : 85.0,
"max" : 90.0,
"avg" : 87.5,
"sum" : 175.0
}
}
Проблема:
Хотя это решение работает для простого запроса выше. Мои реальные запросы могут быть довольно сложными. Этот подход не масштабируется, поскольку существует верхний предел длины скрипта.
Я пытался протестировать вложенные агрегации с фильтрацией агрегации, но кажется, что после перехода во вложенный путь мы не можем выполнить операции И / ИЛИ с не вложенными полями.
Есть ли какой-нибудь лучший способ получить агрегирование статистики для вложенных полей, чтобы при оценке статистики учитывался только максимум конкретных значений вложенных полей.