使用 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 结果相同(如您发布的那样)。