MongoTemplate:按多个字段分组,并带有条件子句。

3

之前我有以下聚合管道。

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);

这个之前运作得很好。然后我修改了原始查询,加入了额外的 overdue 分组选项。

$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 Template查询中实现这个额外的分组条件。我在网上搜索了一下,但大多数结果都使用较旧API的DBObject。有人可以帮助我在Mongo Template中完成吗?


可能是[如何在Spring Data MongoDB中表达复杂的$sum分组表达式]的重复问题(https://stackoverflow.com/questions/46270910/how-to-express-complex-sum-grouping-expression-in-spring-data-mongodb)。 - s7vr
我觉得我之前已经问过这个问题了,所以那个链接中的问题应该是重复的,而不是反过来! :) - Yogesh Pitale
不确定规则是什么。该答案包括最新的更新,您可以将条件运算符作为表达式传递给求和运算符,而无需额外的项目阶段。 - s7vr
1个回答

1

最终我找到了答案!

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

  1. 我使用条件投影来投影一个额外的字段。
  2. 首先执行投影操作。
  3. 然后使用这个附加字段进行分组。

因此,所需的代码更改如下。

步骤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
}...

在步骤一完成后,我在投影中获得了另一个名为"overdue"的字段,其值为1或0,取决于是否满足我的条件。
然后,在分组子句中,我使用了Sum操作符将所有这样的"overdue"字段相加。
GroupOperation group =  Aggregation.group("workflow_stage_current_assignee","control_monitor").count().as("exceptions").sum("overdue").as("overdue");

第三步

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

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

这给了我所需的结果!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接