使用mongoTemplate实现多条件加分组查询方式

2022-07-14,,,,

先来一个常见的错误信息:

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后面,否则结果集不准确。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

《使用mongoTemplate实现多条件加分组查询方式.doc》

下载本文的Word格式文档,以方便收藏与打印。