一 BasicDBObject
整个聚合查询是统计用户的各种状态下的用户数量为场景:
1. 筛选条件:
date 为查询日期:
- BasicDBObject Query = new BasicDBObject();
- Query.put("time",new BasicDBObject("$gte", date + "00:00:00")
- .append("$lte", date + "23:59:59"));
如果有多个条件: 直接加 Query.put("status", 0);
如果有 OR 筛选:
- BasicDBList values = new BasicDBList();
- values.add(new BasicDBObject("status", new BasicDBObject("$exists",false)));
- values.add(new BasicDBObject("status", 0));
- Query.put("$or", values);
其中 new BasicDBObject("$exists",false)) 就是 status 不存在 (mongodb 文档可不等于实体的字段)
2. 拼接 match
DBObject Match = new BasicDBObject("$match", Query);
将上一步的 Query 放入 macth 筛选中
3. 拼接分组条件
此步相当于 SQL 的 Group By
- BasicDBObject GroupBy = new BasicDBObject();// 分组条件
- GroupBy.put("userId", "$userId");// 根据用户 ID 来分组
同第一步的筛选一样, 如果有多个分组可直接添加在后面: GroupBy.put("status", "$status");
4. 分组后查询
首先把分组拼接上:
DBObject Select = new BasicDBObject("_id", GroupBy);
如果我们要对分组后的数据进行操作:(这里是用户的统计数量)
Select.put("count", new BasicDBObject("$sum", 1));
5. 拼接 $group
DBObject Group = new BasicDBObject("$group", Select);
至此我们拼接, mongodb 的语句到此结束
下面我们开始查询操作:
- import com.mongodb.AggregationOutput;
- import org.springframework.data.mongodb.core.MongoTemplate;
- AggregationOutput Output = mongoTemplate.getCollection("这里是 mongodb 的数据表名")
- .aggregate(Match, Group);
读取查询结果:
- Iterable <DBObject> map = Output.results();
- // 遍历 map
- for (DBObject dbObject: map) {
- // 这里读取到的 map 为 {"_id":{"userId":1,"status"0}}...
- Map <String,
- Object> resultMap = (Map <String, Object> ) dbObject.get("_id");
- // 这里截取掉. 0
- Integer userId = Integer.parseInt(CommUtil.toString(ausgMap.get("userId")).replace(".0", ""));
- // 在这里我们就可以对我们的数据进行操作了;
- Integer count = Integer.parseInt(CommUtil.toString(dbObject.get("count")));
- }
二 DBObject
不多说, 如果大家觉得第一种方法特别长篇大论, 那么下面我给大家带来一种代码更简洁的聚合查询:
直接上代码吧
1. 注意导入的包:
- import com.mongodb.DBObject; import com.mongodb.util.JSON;
- 2.$macth:
- (beginDay - 查询开始日期; endDay - 查询结束日期)
- DBObject match = (DBObject) JSON.parse("{$match:{'status':'1','time':
- {$gte:'"+beginDay+"',$lte:'"+endDay+"'}}}");
- 3.$group:
- (以 userId 分组, 统计用户数量, 累加 amout 字段值, 取 amout 字段最大值)
- DBObject group = (DBObject) JSON.parse("{$group:{_id:'$userId',
- count:{$sum:1},total:{$sum:'$amount'},maxSigle:{$max:'$amount'}}}");
条件拼接完, 开始查询:
- List<DBObject> list = new ArrayList<DBObject>();
- list.add(match); list.add(group);
- AggregationOutput Output = mongoTemplate.getCollection("表名").aggregate(list);
遍历结果就不用在说了上面已经详细描述了
第二种方法是不是比一种方式简单多了但是比较考验自身对 mongodb 语句熟悉性
扩展
接着上面的方法进行扩展
- //status 为 0 或者为 1 ; type 不为 11;time 在 beginDay ~ endDay 时间段内
- DBObject match = (DBObject) JSON.parse("{$match:{'status':{$in:['0','1']},
- type:{$ne:11},'time':{$gte:'"+beginDay+"',$lte:'"+endDay+"'}}}");
- // 以用户 Id 分组, 统计查询次数, 取最后一次 time 的时间
- DBObject group = (DBObject) JSON.parse("{$group:{_id:'$userId',
- count:{$sum:1},lastTime:{$max:'$time'} }}");
- // 在上一步统计出的结果中筛选次数大于 100 的数据
- DBObject groupMatch = (DBObject) JSON.parse("{$match:{count:{$gte:100}}}");
- //$project---- 查询结果中需要显示哪些字段, 显示则设置为 1 如下需要不显示_id 域 (字段), 则需如下指定:
- //db. 集合名. aggregate( [ { $project : { _id: 0, count: 1 , lastSuccTime: 1 } } ] )
- DBObject project = (DBObject) JSON.parse("{$project:{_id:1,count:1,lastSuccTime:1}}");
- DBObject sort = (DBObject) JSON.parse("{$sort:{'count':-1}}");// 排序
- List<DBObject> list = new ArrayList<DBObject>();
- list.add(match);
- list.add(group);
- list.add(groupMatch);
- list.add(project);
- list.add(sort);
- AggregationOutput catchOutPut = mongoTemplate.getCollection("表名")
- .aggregate(list);// 查询结果
三 BasicDBObject + 脚本语句
- BasicDBObject groupIndex = new BasicDBObject();
- BasicDBObject distinctQuery = new BasicDBObject();
- distinctQuery.put("userId", new BasicDBObject("$in", userIds));//UserIds 数组
- BasicDBObject initIndex = new BasicDBObject();
- initIndex.put("count", 0);// 给 count 赋初值
- // 脚本 (doc 代表数据库的数据. prev 代表查询结果 //prev.count 这里的 count 就是上一步 initIndex 的 count)
- String reduce = "function(doc, prev) {if(doc.status==0){prev.count+= 1;};}";
- List<Map<String, Object>> basicDBList = (List<Map<String, Object>>) mongoTemplate.
- getCollection("Collection").group(groupIndex, distinctQuery, initIndex, reduce, null);
最后循环遍历 List 即可得到结果 PS:group 这种聚合方式有个限制条件 ---> 超过 20000 数据就会报错
以上就是我在普通业务处理中用到 mongodb 聚合处理如果有更好的方法或是有需要改进的地方
来源: https://juejin.im/post/5ab8a2306fb9a028d9372666