我在 MongoDB 中写了一个查询,如下所示:
db.getCollection('student').aggregate(
[
{
$match: { "student_age" : { "$ne" : 15 } }
},
{
$group:
{
_id: "$student_name",
count: {$sum: 1},
sum1: {$sum: "$student_age"}
}
}
])
换句话说,我想取出15岁以下的学生人数和他们年龄的总结。查询工作正常,我得到两个数据项。
在我的应用程序中,我想通过 Spring Data 进行查询。 我写了以下代码:
Criteria where = Criteria.where("AGE").ne(15);
Aggregation aggregation = Aggregation.newAggregation(
Aggregation.match(where),
Aggregation.group().sum("student_age").as("totalAge"),
count().as("countOfStudentNot15YearsOld"));
运行此代码时,输出查询将为:
"aggregate" : "MyDocument", "pipeline" :
[ { "$match" { "AGE" : { "$ne" : 15 } } },
{ "$group" : { "_id" : null, "totalAge" : { "$sum" : "$student_age" } } },
{ "$count" : "countOfStudentNot15YearsOld" }],
"cursor" : { "batchSize" : 2147483647 }
不幸的是,结果只是countOfStudentNot15YearsOld
项。
我想像我的原生查询一样获取结果。
答案 0 :(得分:1)
如果您要求返回“15”和“非15”的分组,那么您正在寻找$cond
运算符,该运算符将允许基于条件评估的“分支”。
从“shell”内容中你可以像这样使用它:
db.getCollection('student').aggregate([
{ "$group": {
"_id": null,
"countFiteen": {
"$sum": {
"$cond": [{ "$eq": [ "$student_age", 15 ] }, 1, 0 ]
}
},
"countNotFifteen": {
"$sum": {
"$cond": [{ "$ne": [ "$student_age", 15 ] }, 1, 0 ]
}
},
"sumNotFifteen": {
"$sum": {
"$cond": [{ "$ne": [ "$student_age", 15 ] }, "$student_age", 0 ]
}
}
}}
])
因此,您使用$cond
执行逻辑测试,在这种情况下,当前文档中的"student_age"
是否为15
,那么您可以返回一个数值作为响应,这里是1
用于“计数”或实际字段值,而这是您想要发送到累加器的内容。简而言之,它是一个“三元”操作符或if/then/else
条件(实际上可以用更具表现力的形式用键显示),您可以用它来测试条件并决定返回什么。
对于spring mongodb实现,使用ConditionalOperators.Cond
构造相同的BSON表达式:
import org.springframework.data.mongodb.core.aggregation.*;
ConditionalOperators.Cond isFifteen = ConditionalOperators.when(new Criteria("student_age").is(15))
.then(1).otherwise(0);
ConditionalOperators.Cond notFifteen = ConditionalOperators.when(new Criteria("student_age").ne(15))
.then(1).otherwise(0);
ConditionalOperators.Cond sumNotFifteen = ConditionalOperators.when(new Criteria("student_age").ne(15))
.thenValueOf("student_age").otherwise(0);
GroupOperation groupStage = Aggregation.group()
.sum(isFifteen).as("countFifteen")
.sum(notFifteen).as("countNotFifteen")
.sum(sumNotFifteen).as("sumNotFifteen");
Aggregation aggregation = Aggregation.newAggregation(groupStage);
所以基本上你只是延伸了这个逻辑,使用.then()
获取“常量”值,例如1
用于“计数”,.thenValueOf()
用于实际需要“值“来自文档的字段,因此基本上等于"$student_age"
,如公共shell表示法所示。
由于ConditionalOperators.Cond
共享AggregationExpression
接口,因此可以与接受.sum()
而不是字符串的形式的AggregationExpression
一起使用。这是对spring mongo的过去版本的改进,这将要求您执行$project
阶段,以便在执行$group
之前为评估表达式提供实际文档属性。
如果你想要的只是复制spring mongodb的原始查询,那么你的错误是使用$count
聚合阶段,而不是追加到group()
:
Criteria where = Criteria.where("AGE").ne(15);
Aggregation aggregation = Aggregation.newAggregation(
Aggregation.match(where),
Aggregation.group()
.sum("student_age").as("totalAge")
.count().as("countOfStudentNot15YearsOld")
);