一组中的两个总计
Two Aggregate Totals in One Group
我在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
项。
我想像我的本机查询一样获取结果。
如果您要求 return 对“15”和 "not 15" 进行分组,那么您正在寻找 $cond
运算符,它将允许 "branching" 基于条件评估。
根据 "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
,那么你可以return 一个响应的数值,这里是 1
用于 "counting" 或实际字段值,当这是你想要发送到累加器的值时。简而言之,它是一个 "ternary" 运算符或 if/then/else
条件(实际上可以用键以更具表现力的形式显示),您可以使用它来测试条件并决定 return.
对于 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()
作为 "constant" 值,例如 1
作为 "counts",以及 .thenValueOf()
您实际上需要文档中某个字段的 "value",因此基本上等于 "$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")
);
我在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
项。
我想像我的本机查询一样获取结果。
如果您要求 return 对“15”和 "not 15" 进行分组,那么您正在寻找 $cond
运算符,它将允许 "branching" 基于条件评估。
根据 "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
,那么你可以return 一个响应的数值,这里是 1
用于 "counting" 或实际字段值,当这是你想要发送到累加器的值时。简而言之,它是一个 "ternary" 运算符或 if/then/else
条件(实际上可以用键以更具表现力的形式显示),您可以使用它来测试条件并决定 return.
对于 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()
作为 "constant" 值,例如 1
作为 "counts",以及 .thenValueOf()
您实际上需要文档中某个字段的 "value",因此基本上等于 "$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")
);