问题
What I want to achieve: I want my "age" aggregation to not be filtered by the query filter and I want to be able to apply filters to it.
So if I start with this query:
{
"query":{
"filtered":{
"filter":{ "terms":{ "family_name":"Brown" } } //filter_1
}
},
"aggs":{
"young_age":{
"filter":{
"range":{ "lt":40, "gt":18 } //filter_2
},
"aggs":{
"age":{
"terms":{
"field":"age"
}
}
}
}
}
}
My aggregation "young_age" will be filtered by both filter_1 and filter_2. I don't want my aggregation to be filtered by filter_1.
As I was looking into the documentation, I thought global aggregation would solve my problem, and I wrote that query:
{
"query":{
"filtered":{
"filter":{ "terms":{ "family_name":"Brown" } } //filter_1
}
},
"aggs":{
"young_age":{
"global":{}, //<----------- add global
"filter":{
"range":{ "lt":40, "gt":18 } //filter_2
},
"aggs":{
"age":{
"terms":{
"field":"age"
}
}
}
}
}
}
But then elastic search complains about my filter_2:
""" Found two aggregation type definitions [age] in [global] and [filter] """
And of course if I remove the filter_2:
{
"query":{
"filtered":{
"filter":{
"terms":{
"family_name":"Brown"
}
}
}
},
"aggs":{
"young_age":{
"global":{},
"aggs":{
"age":{
"terms":{
"field":"age"
}
}
}
}
}
}
Then my aggregation won't be filtered by filter_1 (as expected).
So how am I suppose to apply filter_2 to my global aggregation? Or how am I supposed to achieved that? I remember writing something similar with the facet filters...
回答1:
In my opinion this is the typical use case of a post_filter. As the doc says:
The post_filter is applied to the search hits at the very end of a search request, after aggregations have already been calculated
Your query will look like:
{
"post_filter":{
"terms":{
"family_name":"Brown" //filter_1
}
},
"aggs":{
"young_age":{
"filter":{
"range":{ "lt":40, "gt":18 } //filter_2
},
"aggs":{
"age":{
"terms":{
"field":"age"
}
}
}
}
}
}
In this case the search hits are all the documents in the index. Then the aggregation is calculated (before filter_1). And after that the post_filter
with the filter_1 will be executed.
Edit: As you said in your commend you have many aggregations and only one that shouldn't be affected by filter_1
I fixed your query using global aggregation
{
"query": {
"filtered": {
"filter": {
"term": {
"family_name": "Brown"
}
}
}
},
"aggs": {
"young_age": {
"global": {},
"aggs": {
"filter2": {
"filter": {
"range": {
"lt": 40,
"gt": 18
}
},
"aggs": {
"age": {
"terms": {
"field": "age"
}
}
}
}
}
}
}
}
回答2:
globals and filters are not allowed at same level. you have to put filter at one level inside to global aggregation.
something like this should do for you.
{
"query":{
"filtered":{
"filter":{
"terms":{
"family_name":"Brown"
}
}
}
},
"aggs":{
"young_age":{
"global":{},
"aggs":{
"filter": {"term": {"family_name": "Brown"}}, #or {"bool": {"filter": {"term": {"family_name": "Brown"}}}}
"aggs": {
"age":{
"terms":{
"field":"age"
}
}
}
}
}
}
}
来源:https://stackoverflow.com/questions/31670668/how-to-filter-an-elasticsearch-global-aggregation