example - Cómo realizar una agregación de canalización sin devolver todos los depósitos en Elasticsearch
elasticsearch cardinality (1)
Estoy usando Elasticsearch 2.3 y estoy tratando de realizar un cálculo de dos pasos utilizando una agregación de canalización. Solo me interesa el resultado final de mi agregación de canalizaciones, pero Elasticsearch devuelve toda la información de los depósitos.
Como tengo una gran cantidad de cubos (decenas o cientos de millones), esto es prohibitivo. Desafortunadamente, no puedo encontrar una forma de decirle a Es que no devuelva toda esta información.
Aquí hay un ejemplo de juguete. Tengo un índice de test-index
con un tipo de documento obj
. obj
tiene dos campos, key
y values
.
curl -XPOST ''http://10.10.0.7:9200/test-index/obj'' -d ''{
"value": 100,
"key": "foo"
}''
curl -XPOST ''http://10.10.0.7:9200/test-index/obj'' -d ''{
"value": 20,
"key": "foo"
}''
curl -XPOST ''http://10.10.0.7:9200/test-index/obj'' -d ''{
"value": 50,
"key": "bar"
}''
curl -XPOST ''http://10.10.0.7:9200/test-index/obj'' -d ''{
"value": 60,
"key": "bar"
}''
curl -XPOST ''http://10.10.0.7:9200/test-index/obj'' -d ''{
"value": 70,
"key": "bar"
}''
Quiero obtener el valor promedio (sobre todas las key
s) del value
mínimo de obj
s con la misma key
s. Un promedio de mínimos.
Elasticsearch me permite hacer esto:
curl -XPOST ''http://10.10.0.7:9200/test-index/obj/_search'' -d ''{
"size": 0,
"query": {
"match_all": {}
},
"aggregations": {
"key_aggregates": {
"terms": {
"field": "key",
"size": 0
},
"aggs": {
"min_value": {
"min": {
"field": "value"
}
}
}
},
"avg_min_value": {
"avg_bucket": {
"buckets_path": "key_aggregates>min_value"
}
}
}
}''
Pero esta consulta devuelve el mínimo para cada segmento, aunque no lo necesito:
{
"took": 21,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 4,
"max_score": 0,
"hits": [
]
},
"aggregations": {
"key_aggregates": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "bar",
"doc_count": 2,
"min_value": {
"value": 50
}
},
{
"key": "foo",
"doc_count": 2,
"min_value": {
"value": 20
}
}
]
},
"avg_min_value": {
"value": 35
}
}
}
¿Hay alguna manera de deshacerse de toda la información dentro de "buckets": [...]
? Solo estoy interesado en avg_min_value
.
Esto podría no parecer un problema en este ejemplo de juguete, pero cuando el número de key
diferentes no es grande (decenas o cientos de millones), la respuesta de la consulta es prohibitivamente grande y me gustaría podarlo.
¿Hay alguna manera de hacer esto con Elasticsearch? ¿O estoy modelando mal mis datos?
NB: no es aceptable agregar previamente mis datos por clave, ya que la parte match_all
de mi consulta puede ser reemplazada por filtros complejos y desconocidos.
NB2: cambiar el size
a un número no negativo en mis terms
agregación no es aceptable porque cambiaría el resultado.
Tuve el mismo problema y después de investigar un poco encontré una solución y pensé que la compartiría aquí.
Puede usar la función Filtrado de respuesta para filtrar la parte de la respuesta que desea recibir.
Debería poder lograr lo que desea al agregar el parámetro de consulta filter_path=aggregations.avg_min_value
a la URL de búsqueda. En el caso de ejemplo, debería ser similar a esto:
curl -XPOST ''http://10.10.0.7:9200/test-index/obj/_search?filter_path=aggregations.avg_min_value'' -d ''{
"size": 0,
"query": {
"match_all": {}
},
"aggregations": {
"key_aggregates": {
"terms": {
"field": "key",
"size": 0
},
"aggs": {
"min_value": {
"min": {
"field": "value"
}
}
}
},
"avg_min_value": {
"avg_bucket": {
"buckets_path": "key_aggregates>min_value"
}
}
}
}''
PD: si encuentras otra solución, ¿te importaría compartirla aquí? ¡Gracias!