MongoTemplate:使用条件子句对多个字段进行分组
MongoTemplate : group by on multiple fields with condition clause
之前我在下面提到过聚合管道。
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 模板查询中实现这个额外的组子句。我在 Internet 上进行了搜索,但大多数结果都使用旧 API 中的 DBObject。任何人都可以用 Mongo 模板帮助我吗?
终于找到答案了!
由于找不到使用 Mongo 模板有条件地对字段进行分组的方法,因此我不得不调整聚合管道本身的逻辑。
- 我使用条件投影来投影一个额外的字段。
- 先进行投影操作
- 然后使用这个附加字段执行分组。
因此需要进行如下代码更改。
步骤 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);
这给了我要求的结果!
之前我在下面提到过聚合管道。
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 模板查询中实现这个额外的组子句。我在 Internet 上进行了搜索,但大多数结果都使用旧 API 中的 DBObject。任何人都可以用 Mongo 模板帮助我吗?
终于找到答案了!
由于找不到使用 Mongo 模板有条件地对字段进行分组的方法,因此我不得不调整聚合管道本身的逻辑。
- 我使用条件投影来投影一个额外的字段。
- 先进行投影操作
- 然后使用这个附加字段执行分组。
因此需要进行如下代码更改。
步骤 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);
这给了我要求的结果!