Mongodb 统计某个字段的和,可以使用聚合函数。
数据结构如下:
- > db.message.findOne()
- {
- "_class" : "com.cyou.appwiki.bean.Message",
- "_id" : ObjectId("53997f80c451bf833288b882"),
- "content" : "power9li的回答2",
- "fromNick" : "power9li",
- "fromUid" : "5176923980",
- "pic1" : null,
- "pic2" : null,
- "pic3" : null,
- "qid" : "53997f4dc451bf833288b880",
- "time" : NumberLong("1402568587464"),
- "toUid" : "F34780D6A3CA543DB020D584A91CC8BB",
- "unreadCount" : 2
- }
我要统计的是某个toUid的unreadCount的总数
我发现有两种方法可以实现,第一种是mapReduce的方式,我在《MongodDB权威指南》书里看到的:
- db.runCommand({"group":{
- "ns":"message",
- "key":"toUid",
- "initial":{"total":0},
- "$reduce" : function(doc,prev){
- prev.total += doc.unreadCount;
- },
- "condition":{"toUid":"F34780D6A3CA543DB020D584A91CC8BB"}
- }});
返回的结果格式:
- {
- "retval" : [
- {
- "total" : 13
- }
- ],
- "count" : 5,
- "keys" : 1,
- "ok" : 1
- }
第二种方法是在 http://www.w3cschool.cc/mongodb/mongodb-aggregate.html 看到的:
- db.message.aggregate([
- { $match : { "toUid" : "F34780D6A3CA543DB020D584A91CC8BB"}},
- { $group : { _id : "$toUid", num_tutorial : {$sum : "$unreadCount"} }}
- ]);
返回的结果:
- {
- "result" : [
- {
- "_id" : "F34780D6A3CA543DB020D584A91CC8BB",
- "num_tutorial" : 13
- }
- ],
- "ok" : 1
- }
在使用spring-mongo进行开发的时候,也对应两种方法
1:(老方法,支持spring-mongo所有版本)
- public long findNewMessage(Integer appId, String userId) {
- Long total = 0l;
- String reduce = "function(doc, aggr){" +
- " aggr.total += doc.unreadCount;" +
- " }";
- Query query = Query.query(Criteria.where("toUid").is(userId).and("appId").is(appId));
- DBObject result = mongoTemplate.getCollection("message").group(new BasicDBObject("toUid", 1),
- query.getQueryObject(),
- new BasicDBObject("total", total),
- reduce);
- Map<String,BasicDBObject> map = result.toMap();
- if(map.size() > 0){
- BasicDBObject bdbo = map.get("0");
- if(bdbo != null && bdbo.get("total") != null)
- total = bdbo.getLong("total");
- }
- return total;
- }
方法2(只有spring-mongo 3.2以上才支持)
- public long getNewMessageCount(Integer appId, String userId){
- Long total = 0l;
- Aggregation aggregation = Aggregation.newAggregation(
- match(Criteria.where("toUid").is(userId).and("appId").is(appId)),
- group("toUid").sum("unreadCount").as("total")
- );
- AggregationResults<StateStats> ar = mongoTemplate.aggregate(aggregation, "message", StateStats.class);
- List<StateStats> list = ar.getMappedResults();
- if(list.size() > 0){
- total = list.get(0).total;
- }
- return total;
- }
原文:http://garyli.iteye.com/blog/2079158