Агрегат ElasticSearch для вложенного поля со сценарием
У меня есть следующее сопоставление в моем индексе ElasticSearch (упрощенное, поскольку другие поля не имеют значения):
{
"test": {
"mappings": {
"properties": {
"name": {
"type": "keyword"
},
"entities": {
"type": "nested",
"properties": {
"text_property": {
"type": "text"
},
"float_property": {
"type": "float"
}
}
}
}
}
}
}
Данные выглядят так (опять же упрощенно):
[
{
"name": "a",
"entities": [
{
"text_property": "foo",
"float_property": 0.2
},
{
"text_property": "bar",
"float_property": 0.4
},
{
"text_property": "baz",
"float_property": 0.6
}
]
},
{
"name": "b",
"entities": [
{
"text_property": "foo",
"float_property": 0.9
}
]
},
{
"name": "c",
"entities": [
{
"text_property": "foo",
"float_property": 0.2
},
{
"text_property": "bar",
"float_property": 0.9
}
]
}
]
Я пытаюсь выполнить агрегацию ведра по максимальному значению для каждого документа. Таким образом, для приведенного выше примера желаемым ответом будет следующее:
...
{
"buckets": [
{
"key": "0.9",
"doc_count": 2
},
{
"key": "0.6",
"doc_count": 1
}
]
}
как документ
a
наибольшее вложенное значение для
float_property
0,6,
b
это 0,9 и
c
это 0,9.
Я пробовал использовать смесь
nested
а также
aggs
, вместе с
runtime_mappings
, но я не уверен, в каком порядке их использовать и возможно ли это вообще.
2 ответа
Я создал индекс с вашими сопоставлениями, изменив тип float_property на double.
PUT testindex
{
"mappings": {
"properties": {
"name": {
"type": "keyword"
},
"entities": {
"type": "nested",
"include_in_parent": true,
"properties": {
"text_property": {
"type": "text"
},
"float_property": {
"type": "double"
}
}
}
}
}
}
Добавлено «include_in_parent»: true для «вложенного» типа.
Проиндексировали документы:
PUT testindex/_doc/1
{
"name": "a",
"entities": [
{
"text_property": "foo",
"float_property": 0.2
},
{
"text_property": "bar",
"float_property": 0.4
},
{
"text_property": "baz",
"float_property": 0.6
}
]
}
PUT testindex/_doc/2
{
"name": "b",
"entities": [
{
"text_property": "foo",
"float_property": 0.9
}
]
}
PUT testindex/_doc/3
{
"name": "c",
"entities": [
{
"text_property": "foo",
"float_property": 0.2
},
{
"text_property": "bar",
"float_property": 0.9
}
]
}
Затем агрегация терминов по вложенному полю:
POST testindex/_search
{
"from": 0,
"size": 30,
"query": {
"match_all": {}
},
"aggregations": {
"entities.float_property": {
"terms": {
"field": "entities.float_property"
}
}
}
}
Это дает результат агрегации, как показано ниже:
"aggregations" : {
"entities.float_property" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : 0.2,
"doc_count" : 2
},
{
"key" : 0.9,
"doc_count" : 2
},
{
"key" : 0.4,
"doc_count" : 1
},
{
"key" : 0.6,
"doc_count" : 1
}
]
}
}
Мне удалось понять это в конце концов.
Две вещи, которые я не понял, были:
- Вы можете предоставить
script
вместоfield
ключ к агрегации ведра. - Вместо использования запросов вы можете получить доступ к вложенным значениям напрямую, используя
params._source
.
Сочетание этих двух вещей позволило мне написать правильный запрос:
{
"size": 0,
"aggs": {
"max.float_property": {
"terms": {
"script": "double max = 0; for (item in params._source.entities) { if (item.float_property > max) { max = item.float_property; }} return max;"
}
}
}
}
Ответ:
{
...
"aggregations": {
"max.float_property": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "0.9",
"doc_count": 2
},
{
"key": "0.6",
"doc_count": 1
}
]
}
}
}
Однако я запутался, потому что думал, что правильный способ доступа к полям - использовать
nested
тип запроса. К сожалению, для этого очень мало документации, поэтому я все еще не уверен, является ли это предполагаемым/правильным способом агрегирования вложенных полей со сценариями.