使用 Spring 数据 Mongo 在 mongodb 聚合中分组时,如何获取具有非空数组字段的元素的计数?
How to get the count of element with non-empty-array-field when group in mongodb aggregate using Spring Data Mongo?
我在一个名为 mail_test
的集合中有以下文档。其中一些有一个 tags
字段,它是一个数组:
/* 1 */
{
"_id" : ObjectId("601a7c3a57c6eb4c1efb84ff"),
"email" : "aaaa@bbb.com",
"content" : "11111"
}
/* 2 */
{
"_id" : ObjectId("601a7c5057c6eb4c1efb8590"),
"email" : "aaaa@bbb.com",
"content" : "22222"
}
/* 3 */
{
"_id" : ObjectId("601a7c6d57c6eb4c1efb8675"),
"email" : "aaaa@bbb.com",
"content" : "33333",
"tags" : [
"x"
]
}
/* 4 */
{
"_id" : ObjectId("601a7c8157c6eb4c1efb86f4"),
"email" : "aaaa@bbb.com",
"content" : "4444",
"tags" : [
"yyy",
"zzz"
]
}
有两个非空标签的文档,所以我希望结果为 2。
我使用以下语句聚合并获得正确的 tag_count
:
db.getCollection('mail_test').aggregate([{$group:{
"_id":null,
"all_count":{$sum:1},
"tag_count":{"$sum":{$cond: [ { $ne: ["$tags", undefined] }, 1, 0]}}
//if replace `undefined` with `null`, I got the tag_count as 4, that is not what I want
//I also have tried `$exists`, but it cannot be used here.
}}])
结果是:
{
"_id" : null,
"all_count" : 4.0,
"tag_count" : 2.0
}
并且我在 java 中使用 spring 数据 mongo 来执行此操作:
private void test(){
Aggregation agg = Aggregation.newAggregation(
Aggregation.match(new Criteria()),//some condition here
Aggregation.group(Fields.fields()).sum(ConditionalOperators.when(Criteria.where("tags").ne(null)).then(1).otherwise(0)).as("tag_count")
//I need an `undefined` instead of `null`,or is there are any other solution?
);
AggregationResults<MailTestGroupResult> results = mongoTemplate.aggregate(agg, MailTest.class, MailTestGroupResult.class);
List<MailTestGroupResult> mappedResults = results.getMappedResults();
int tag_count = mappedResults.get(0).getTag_count();
System.out.println(tag_count);//get 4,wrong
}
我需要 undefined
而不是 null
,但我不知道该怎么做,或者有其他解决方案吗?
您可以在查询的 $group
阶段使用聚合运算符检查字段 tags
是否存在或 不存在 以及以下构造之一(计算 tag_count
值):
"tag_count":{ "$sum": { $cond: [ { $gt: [ { $size: { $ifNull: ["$tags", [] ] }}, 0 ] }, 1, 0] }}
// - OR -
"tag_count":{ "$sum": { $cond: [ $eq: [ { $type: "$tags" }, "array" ] }, 1, 0] }
两者,return 结果相同(如您发布的那样)。
我在一个名为 mail_test
的集合中有以下文档。其中一些有一个 tags
字段,它是一个数组:
/* 1 */
{
"_id" : ObjectId("601a7c3a57c6eb4c1efb84ff"),
"email" : "aaaa@bbb.com",
"content" : "11111"
}
/* 2 */
{
"_id" : ObjectId("601a7c5057c6eb4c1efb8590"),
"email" : "aaaa@bbb.com",
"content" : "22222"
}
/* 3 */
{
"_id" : ObjectId("601a7c6d57c6eb4c1efb8675"),
"email" : "aaaa@bbb.com",
"content" : "33333",
"tags" : [
"x"
]
}
/* 4 */
{
"_id" : ObjectId("601a7c8157c6eb4c1efb86f4"),
"email" : "aaaa@bbb.com",
"content" : "4444",
"tags" : [
"yyy",
"zzz"
]
}
有两个非空标签的文档,所以我希望结果为 2。
我使用以下语句聚合并获得正确的 tag_count
:
db.getCollection('mail_test').aggregate([{$group:{
"_id":null,
"all_count":{$sum:1},
"tag_count":{"$sum":{$cond: [ { $ne: ["$tags", undefined] }, 1, 0]}}
//if replace `undefined` with `null`, I got the tag_count as 4, that is not what I want
//I also have tried `$exists`, but it cannot be used here.
}}])
结果是:
{
"_id" : null,
"all_count" : 4.0,
"tag_count" : 2.0
}
并且我在 java 中使用 spring 数据 mongo 来执行此操作:
private void test(){
Aggregation agg = Aggregation.newAggregation(
Aggregation.match(new Criteria()),//some condition here
Aggregation.group(Fields.fields()).sum(ConditionalOperators.when(Criteria.where("tags").ne(null)).then(1).otherwise(0)).as("tag_count")
//I need an `undefined` instead of `null`,or is there are any other solution?
);
AggregationResults<MailTestGroupResult> results = mongoTemplate.aggregate(agg, MailTest.class, MailTestGroupResult.class);
List<MailTestGroupResult> mappedResults = results.getMappedResults();
int tag_count = mappedResults.get(0).getTag_count();
System.out.println(tag_count);//get 4,wrong
}
我需要 undefined
而不是 null
,但我不知道该怎么做,或者有其他解决方案吗?
您可以在查询的 $group
阶段使用聚合运算符检查字段 tags
是否存在或 不存在 以及以下构造之一(计算 tag_count
值):
"tag_count":{ "$sum": { $cond: [ { $gt: [ { $size: { $ifNull: ["$tags", [] ] }}, 0 ] }, 1, 0] }}
// - OR -
"tag_count":{ "$sum": { $cond: [ $eq: [ { $type: "$tags" }, "array" ] }, 1, 0] }
两者,return 结果相同(如您发布的那样)。