数据结构:
{
"year": 2020,
"college": {
"code": "10003",
"cnName": "清华大学",
"categories": ["综合"]
},
"rank": 1
}
需求:
按照College.Categories
数组中的项分组,取每组Rank
前三
查询脚本:
POST myindex/_search
{
"query": {
"term": {
"year": {
"value": "2020"
}
}
},
"size": 0,
"aggs": {
"categories": {
"terms": {
"field": "college.categories" //指定用于分组的字段
},
"aggs": {
"ranks": {
"top_hits": { //top_hits函数用于排序
"sort": [ //指定排序的方式和字段
{
"rank": {
"order": "asc"
}
}
],
"size": 3, //指定每组的条数
"_source": { //指定返回的字段,如果不指定,会返回全部的字段
"includes": [
"college.cnName",
"college.code"
]
}
}
}
}
}
}
}
查询结果:
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1252,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"categories" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 532,
"buckets" : [
{
"key" : "综合",
"doc_count" : 416,
"ranks" : {
"hits" : {
"total" : {
"value" : 416,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
"_index" : "myindex",
"_type" : "_doc",
"_id" : "d21c5bc6-416b-4bc3-a836-27bda316d215",
"_score" : null,
"_source" : {
"college" : {
"code" : "xxx",
"cnName" : "清华大学"
}
},
"sort" : [
1
]
},
{
"_index" : "myindex",
"_type" : "_doc",
"_id" : "1f9a04ff-b58e-4c49-aa73-352ed52f15fe",
"_score" : null,
"_source" : {
"college" : {
"code" : "xxx",
"cnName" : "北京大学"
}
},
"sort" : [
2
]
},
{
"_index" : "myindex",
"_type" : "_doc",
"_id" : "1826c73d-3062-4f49-9bda-0b63d065e3fe",
"_score" : null,
"_source" : {
"college" : {
"code" : "xxx",
"cnName" : "浙江大学"
}
},
"sort" : [
3
]
}
]
}
}
},
{
"key" : "理工",
"doc_count" : 332,
"ranks" : {
"hits" : {
"total" : {
"value" : 332,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
"_index" : "myindex",
"_type" : "_doc",
"_id" : "1c71ea27-f29c-44a4-9cd9-ae0d147d9e5b",
"_score" : null,
"_source" : {
"college" : {
"code" : "xxx",
"cnName" : "中国科学院大学"
}
},
"sort" : [
12
]
},
{
"_index" : "myindex",
"_type" : "_doc",
"_id" : "f1838123-5c5b-483a-8e79-502c22276509",
"_score" : null,
"_source" : {
"college" : {
"code" : "xxx",
"cnName" : "北京航空航天大学"
}
},
"sort" : [
13
]
},
{
"_index" : "myindex",
"_type" : "_doc",
"_id" : "2bf43eb9-b23e-457a-923d-e37e8db6107f",
"_score" : null,
"_source" : {
"college" : {
"code" : "xxx",
"cnName" : "哈尔滨工业大学"
}
},
"sort" : [
16
]
}
]
}
}
}
]
}
}
}
翻译成 C#代码:
var response = await Client.SearchAsync<CollegeGlobalRank>(x => x.Index(IndexName)
.Query(y => y.Bool(c => c.Must(conditions)))
.Aggregations(
aggs =>
aggs.Terms("categories", t => t.Field(f => f.College.Categories).Size(count)
.Aggregations(agg => agg.TopHits("ranks", tt => tt.Sort(sort => sort.Ascending(f => f.Rank)).Size(3).Source(source => source.Includes(f => f.Fields(ff => ff.College.CnName, ff => ff.Rank))))))
));
取值:
翻译完之后取值也是花费了一些功夫研究的,取值代码如下:
var result = new List<NameValue<IList<CollegeGlobalRank>>>();
foreach (var aggsItem in response.Aggregations)
{
var buckets = (BucketAggregate)aggsItem.Value;
if (buckets.IsNotNull() && buckets.Items.Count > 0)
{
foreach (var bucket in buckets.Items)
{
var bucketItem = (KeyedBucket<object>)bucket;
foreach (var aggregate in bucketItem.Values)
{
var values = (TopHitsAggregate)aggregate;
var ranks = values.Documents<CollegeGlobalRank>().ToList();
var item = new NameValue<IList<CollegeGlobalRank>>()
{
Name = bucketItem.Key.ToString(),
Value = ranks
};
result.Add(item);
}
}
}
}