MongoTemplate:在带有条件子句的多个字段上分组

时间:2017-09-15 10:36:09

标签: mongodb mongotemplate

之前我曾提到过以下提到的聚合管道。

db.EXCEPTIONS.aggregate(
[{ $match : {
        $and : [
            {workflow_stage_current_assignee : {$ne:null}},
            {CreatedDate:{$gt:ISODate("2017-07-12")}}, 
            {CreatedDate:{$lt:ISODate("2018-07-12")}} 
        ]}
 },
 {
     $group : {_id: {user : "$workflow_stage_current_assignee", cm:"$control_monitor"},
               exceptions:{$sum:1} }   
 },
 { $project : {"user":1,"cm":1,"exceptions":1}},
 { $sort : {"exceptions":1}}

]);

Mongo模板中的相应转换如下。

Calendar fromDate = Calendar.getInstance();
fromDate.set(2016, 7, 12, 0, 0, 0);

Calendar toDate = Calendar.getInstance();
toDate.set(2018, 7, 12, 23, 59, 59);

MatchOperation match = Aggregation.match(new Criteria("workflow_stage_current_assignee").ne(null)
        .andOperator(new Criteria("CreatedDate").gte(new Date(fromDate.getTimeInMillis()))
        .andOperator(new Criteria("CreatedDate").lte(new Date(toDate.getTimeInMillis())))));

GroupOperation group = Aggregation.group("workflow_stage_current_assignee","control_monitor").count().as("exceptions");

ProjectionOperation project = Aggregation.project("workflow_stage_current_assignee","control_monitor","exceptions");

SortOperation sort=Aggregation.sort(Sort.Direction.DESC,"exceptions");

Aggregation aggregation  = Aggregation.newAggregation(match,group,project,sort);

AggregationResults<ExceptionCount> output  = mongoTemplate.aggregate(aggregation, "EXCEPTIONS", ExceptionCount.class);

这很好用。然后我修改了原始查询,如下所示,并添加了额外的分组选项作为逾期。

$group : {_id: {user : "$workflow_stage_current_assignee", cm:"$control_monitor"},
               exceptions:{$sum:1},
               },
               overdue: {$sum : {$cond :[ 
                                    {$gt:["$CreatedDate",ISODate("2017-07-12")]},1,0
                                ]}
               }

但是我不知道如何在Mongo模板查询中实现这个额外的组子句。我在互联网上搜索,但大多数结果使用旧版API中的DBObject。任何人都可以用Mongo模板帮助我吗?

1 个答案:

答案 0 :(得分:0)

最后我找到了答案!

由于我找不到使用Mongo模板有条件地对字段进行分组的方法,我不得不调整聚合管道本身的逻辑。

  1. 我使用条件投影来投射额外的字段。
  2. 首先执行投影操作。
  3. 然后使用此附加字段执行分组。
  4. 所需的代码更改如下所示。

    第1步

    我修改了我的投影子句并添加了另一个条件投影字段,如下所示。

    Cond overdueCondition = ConditionalOperators.when(new Criteria("CreatedDate").gt(new Date())).then(1).otherwise(0);
    ProjectionOperation project = Aggregation.project("workflow_stage_current_assignee","control_monitor","exceptions").and("overdue").applyCondition(overdueCondition);
    

    此操作的结果会将我的结果集减少为:

    {
    "workflow_stage_current_assignee" : "Yogesh",
    "control_monitor" : "P005",
    "exceptions":"",
    "overdue" : 1
    },
    {
    "workflow_stage_current_assignee" : "Yogesh",
    "control_monitor" : "P005",
    "exceptions":"",
    "overdue" : 0
    }...
    

    在第1步之后,我在投影中得到另一个叫做过期的字段,其值为1或0,具体取决于我的条件是否满足。

    第2步

    然后在组子句中我使用Sum运算符来添加所有这些过期字段。

    GroupOperation group =  Aggregation.group("workflow_stage_current_assignee","control_monitor").count().as("exceptions").sum("overdue").as("overdue");
    

    第3步

    最后我修改了我的聚合管道以首先执行投影操作,然后将所有结果分组。

    Aggregation aggregation  = Aggregation.newAggregation(match,project,group,sort);
    

    这给了我所需的结果!