使用mongoTemplate实现多条件加分组查询方式
目录
- mongoTemplate实现多条件查询
- mongoTemplate分组查询的坑
先来一个常见的错误信息:
Due to limitations of the com.mongodb.BasicDocument, you can't add a second '$and' expression specified as '$and :
错误原因:
在一个 Criteria 对象中调用了多次 andOperator() 方法
mongoTemplate实现多条件查询
多个条件的查询只需要创建 Query 对象,然后把需要添加的条件使用 Query 对象的 addCriteria() 方法
// 场景:查询指定时间段内,状态为1的数据 // 入参条件 :beginTime ,endTime ,statue // mongodb字段:time , state // 存放条件的对象 Query condition= new Query(); // 判断时间是否为空 if(beginTime != null && endTime != null){ // 添加大于开始时间小于结束时间的条件 condition.addCriteria(Criteria.where("time").gte(beginTime).lte(endTime)); }else{ // 其中一个为空 分别进行判断 if(beginTime != null){ condition.addCriteria(Criteria.where("time").gte(beginTime)); } if(endTime != null){ condition.addCriteria(Criteria.where("time").lte(endTime)); } } // 添加状态为1条件 if(statue!=null){ condition.addCriteria(Criteria.where("state").is(statue)); }
条件有了后再调用 mongoTemplate.find(condition,返回类型.class,collectionName)
但是...想要分组,得调用 mongoTemplate.group(Criteria criteria , String inputCollectionName , GroupBy groupBy , Class<T> entityClass) 方法 (不是说只能这样才能分组,而是我通过这种方法实现了分组查询)
朋友们,第一个参数条件只能入参 Criteria 对象,而不能入参 Query 对象
结果我发现 Criteria 对象有 andOperator(Criteria ... criteria) 方法
这个方法就厉害了,可以入参数组,也就是说
我们可以把查询条件先存放到一个集合里面(因为数组需要定义长度,如果条件个数不确定,就不能直接定义数组),然后把集合放入数组中,再把数组入参 andOperator(Criteria ... criteria) 方法
// 场景:查询指定时间段内,状态为1的数据 // 入参条件 :beginTime ,endTime ,statue // mongodb字段:time , state // 定义一个存放条件的集合 List<Criteria> criteriaList = new ArrayList<>(); // 定义一个存放条件的数组(暂时不给长度) Criteria[] criteriaArray = {}; // 判断时间是否为空 if(beginTime != null && endTime != null){ // 添加大于开始时间小于结束时间的条件 Criteria between = Criteria.where("time").gte(beginTime).lte(endTime); criteriaList.add(between); }else{ // 其中一个为空 分别进行判断 if(beginTime != null){ Criteria gte = Criteria.where("time").gte(beginTime); criteriaList.add(gte); } if(endTime != null){ Criteria lte = Criteria.where("time").lte(endTime); criteriaList.add(lte); } } // 添加状态为1条件 if(statue!=null){ Criteria isState = Criteria.where("state").is(statue); criteriaList.add(isState); } // 如果有条件 if(criteriaList.size()>0){ // 集合的个数就是数组的长度 criteriaArray = new Criteria[criteriaList.size()]; // 遍历添加到数组中 for(int i = 0 ; i<criteriaList.size(); i++){ criteriaArray[i] = criteriaList.get(i); } }
这种就可以调用 mongoTemplate.group(Criteria criteria , String inputCollectionName , GroupBy groupBy , Class<T> entityClass) 方法进行分组查询了
GroupBy groupBy = new GroupBy("分组字段") .initialDocument("{ count: 0 }") .reduceFunction("function (doc,pre){pre.count +=1 ;}"); // new Criteria().andOperator(criteriaArray) 这个是很关键的一步操作,把刚刚的条件数组放入进入 // groupByResults 这个对象里面内容很多,有兴趣的朋友可以断点进入看一下 GroupByResults groupByResults = mongoTemplate. group(new Criteria().andOperator(criteriaArray), mongodb的collectionName, groupBy, 实体类.class); // 获取分组后的数量 long resultCount = ((List)groupByResults.getRawResults().get("retval")).size();
mongoTemplate分组查询的坑
Aggregation agg = Aggregation.newAggregation( Aggregation.match(new Criteria().orOperator(new Criteria("to").is(ukey), new Criteria().and("fromAccount").is(ukey))), Aggregation.sort(Sort.Direction.DESC,"_id"), Aggregation.group("to","fromAccount") );
Aggregation.group 要排在Aggregation.match后面,否则结果集不准确。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。