一、mongoDB准备数据
db.getCollection('test').insert({ "_id" : "7", "column_id" : "2", "metadata":{ "status" : true, "cp" : "1", "sp" : "2" }, "duration" : 1000 })
...
查看数据duration:1000.0不符合预期,需要在insert时指定类型"duration" : NumberInt(1000)
。
二、mongoDB aggregate实践
根据column_id,status,cp分组;duration求和;获取count数;根据status降序排序,cp升序排序。
db.getCollection('test').aggregate(
[
{$group: {"_id" : {"column_id": "$metadata.column_id", "status": "$metadata.status", "cp": "$metadata.cp"}, duration: {$sum: "$duration"}, count : {$sum : 1}}},
{$project: {"_id": 1, "duration": 1, "count": 1}},
{$sort: {"_id.status": -1, "_id.cp": 1}}
]
)
返回结果count是float类型,并不是int类型,需要指定类型"count": NumberInt(1)
/* 1 */
{
"_id" : {
"column_id" : "2",
"status" : true,
"cp" : "1"
},
"duration" : 2000,
"count" : 2
}
/* 2 */
{
"_id" : {
"column_id" : "1",
"status" : true,
"cp" : "1"
},
"duration" : 2000,
"count" : 2
}
...
三、mongoTemplate aggregate实践
使用mongoTemplate.aggregate(Aggregation aggregation, String collectionName, Class<O> outputType)
方法返回数据,可以通过aggregationResults.getMappedResults()
获得List<Map>数据,也可以通过aggregationResults.getMappedResults()
获取数据,只是获取数据的过程比较复杂,在这里不使用。
AggregationOperation aggregationOperation = Aggregation.group("metadata.column_id", "metadata.status", "metadata.cp")
.sum("duration").as("duration").count().as("count");
AggregationOperation sort = Aggregation.sort(new Sort(Sort.Direction.DESC, "_id.status"))
.and(new Sort(Sort.Direction.ASC, "_id.cp"));
Aggregation aggregation = Aggregation.newAggregation(aggregationOperation, sort);
AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, "navigation_test", Map.class);
List<Map> datas = results.getMappedResults();
for (Map data : datas){
System.out.println(data);
}
四、参考文档
https://docs.mongodb.com/manual/reference/operator/aggregation/