Elasticsearch中每组的最大值总和
Sum of max per group in Elasticsearch
我想在 Elasticsearch 数据中搜索每个组的最大总和。例如:
数据为:
id | gId | cost
----|-----|------
1 | 1 | 20
2 | 1 | 15
3 | 2 | 30
4 | 1 | 30 *
5 | 2 | 40 *
6 | 1 | 20
7 | 2 | 30
8 | 3 | 45 *
9 | 1 | 10
我使用 sum_bucket 对每个组的最大值进行求和。这是我的查询:
{
"aggs": {
"T1":{
"terms": {
"field": "gId",
"size":3
},
"aggs":{
"MAX_COST":{
"max": {
"field": "cost"
}
}
}
},
"T2":{
"sum_bucket": {
"buckets_path": "T1>MAX_COST"
}
}
},
"size": 0
}
查询响应是
"T1": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [ |
{ |
"key": 1, |
"doc_count": 5, |
"MAX": { |
"value": 30 |
} |
}, |
{ | How can ignore this part to return
"key": 2, | from elasticsearch query response
"doc_count": 3, |
"MAX": { |
"value": 40 |
} |
}, |
{ |
"key": 3, |
"doc_count": 1, |
"MAX": { |
"value": 45 |
} |
} |
]
},
"T2": {
"value": 115
}
T2.value 是期望的结果。但是我想在查询结果中 T1.buckets 忽略网络性能问题,因为我的数据非常大。通过将 T1.terms.size 设置为特定数字,仅在 T2.value 结果中影响结果的前几名。如何忽略我编写的查询结果中的 T1.buckets 或对每组最大总和问题求和的更好查询?
我不熟悉对聚合时添加的字段执行此操作的 "official" 方法,但是您可以 "hack" 使用 Post filter 选项。
添加一个可以区分 T1 和 T2 的术语,例如 {"exists": {"field": "value"}} 假设您可以使用 "exists" 作为术语。
您可以使用 filter_path
来 return 仅响应的一个子集
var searchResponse = client.Search<Document>(s => s
.FilterPath(new[] { "T2.value" }) // paths to include in response
.Aggregations(a => a
// ... rest of aggs here
)
);
请记住,将 filter_path
与 NEST 一起使用有时会导致无法由内部序列化程序反序列化的响应,因为结构是意外的。在这些情况下,您可以使用暴露在高级客户端上的低级客户端来处理响应
var searchDescriptor = new SearchDescriptor<Document>()
.Aggregations(a => a
// ... rest of aggs here
);
var searchResponse = client.LowLevel.Search<StringResponse>(
"index",
"type",
PostData.Serializable(searchDescriptor),
new SearchRequestParameters
{
QueryString = new Dictionary<string, object>
{
["filter_path"] = "T2.value"
}
});
// do something with JSON string response
var json = searchResponse.Body;
我想在 Elasticsearch 数据中搜索每个组的最大总和。例如:
数据为:
id | gId | cost
----|-----|------
1 | 1 | 20
2 | 1 | 15
3 | 2 | 30
4 | 1 | 30 *
5 | 2 | 40 *
6 | 1 | 20
7 | 2 | 30
8 | 3 | 45 *
9 | 1 | 10
我使用 sum_bucket 对每个组的最大值进行求和。这是我的查询:
{
"aggs": {
"T1":{
"terms": {
"field": "gId",
"size":3
},
"aggs":{
"MAX_COST":{
"max": {
"field": "cost"
}
}
}
},
"T2":{
"sum_bucket": {
"buckets_path": "T1>MAX_COST"
}
}
},
"size": 0
}
查询响应是
"T1": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [ |
{ |
"key": 1, |
"doc_count": 5, |
"MAX": { |
"value": 30 |
} |
}, |
{ | How can ignore this part to return
"key": 2, | from elasticsearch query response
"doc_count": 3, |
"MAX": { |
"value": 40 |
} |
}, |
{ |
"key": 3, |
"doc_count": 1, |
"MAX": { |
"value": 45 |
} |
} |
]
},
"T2": {
"value": 115
}
T2.value 是期望的结果。但是我想在查询结果中 T1.buckets 忽略网络性能问题,因为我的数据非常大。通过将 T1.terms.size 设置为特定数字,仅在 T2.value 结果中影响结果的前几名。如何忽略我编写的查询结果中的 T1.buckets 或对每组最大总和问题求和的更好查询?
我不熟悉对聚合时添加的字段执行此操作的 "official" 方法,但是您可以 "hack" 使用 Post filter 选项。
添加一个可以区分 T1 和 T2 的术语,例如 {"exists": {"field": "value"}} 假设您可以使用 "exists" 作为术语。
您可以使用 filter_path
来 return 仅响应的一个子集
var searchResponse = client.Search<Document>(s => s
.FilterPath(new[] { "T2.value" }) // paths to include in response
.Aggregations(a => a
// ... rest of aggs here
)
);
请记住,将 filter_path
与 NEST 一起使用有时会导致无法由内部序列化程序反序列化的响应,因为结构是意外的。在这些情况下,您可以使用暴露在高级客户端上的低级客户端来处理响应
var searchDescriptor = new SearchDescriptor<Document>()
.Aggregations(a => a
// ... rest of aggs here
);
var searchResponse = client.LowLevel.Search<StringResponse>(
"index",
"type",
PostData.Serializable(searchDescriptor),
new SearchRequestParameters
{
QueryString = new Dictionary<string, object>
{
["filter_path"] = "T2.value"
}
});
// do something with JSON string response
var json = searchResponse.Body;