mongodb - 计算符合给定条件的子文档

标签 mongodb mongodb-query aggregation-framework

我的 Mongo 集合具有以下形式的文档:

{
    ...
    "notifications": [
        {
            "enabled": true,
            "groups": [ "NG1", "NG3" ]
        },
        {
            "enabled": false,
            "groups": []
        }
    ]
}

其中 enabled 是 bool 值,groups 是字符串列表。 我需要执行查询以确定 notifications 中有多少条目具有 enabled = true 并在 groups 中包含给定字符串(例如 NG3).

以前,没有 enabled 属性(稍后根据要求引入),我的查询很简单

db.collection.find({ "notifications.groups": "NG3" })

我尝试了一些与 $and 运算符的组合,但没有成功,所以欢迎任何建议。提前致谢!

最佳答案

建议运行一个聚合框架管道,该管道使用 $filter 的组合。 $size $project 中的数组运算符 流水线步骤。

$filter 运算符将返回一个数组,该数组的子集中的元素与指定条件匹配。 <强> $size 将简单地返回该过滤数组中的元素数。

因此,综上所述,您可以运行此管道,以便您可以确定通知中有多少条目具有 enabled = true 并在组中包含给定的字符串(例如“NG3”):

var pipeline = [
    { "$match": { "notifications.enabled": true, "notifications.groups": "NG3" } },
    {
        "$project": {
            "numberOfEntries": {
                "$size": {
                    "$filter": {
                        "input": "$notifications",
                        "as": "items",
                        "cond": { 
                            "$and": [
                                { "$eq": [ "$$items.enabled", true ] },
                                { "$setIsSubset": [ [ "NG3" ], "$$items.groups" ] }
                            ] 
                        }
                    }
                }
            }
        }
    }
];

db.collection.aggregate(pipeline);

以上适用于 MongoDB 版本 3.2.X 和更新版本。但是,对于涵盖 MongoDB 版本 2.6.X 直至并包括 3.0.X 的解决方案,其他数组运算符如 $map , $setDifference 将是很好的替代运营商 过滤数组。

考虑使用 $map 运算符在 $cond 中使用与上面相同的逻辑作为映射表达式来过滤数组。 <强> $setDifference 运算符然后返回一个集合,其中的元素出现在第一个集合中但不在第二个集合中;即相对于第一组执行第二组的相对恭维。在这种情况下,它将通过 enabledgroups 属性返回包含与父文档无关的元素的最终通知数组。

var pipeline = [   
    { "$match": { "notifications.enabled": true, "notifications.groups": "NG3" } },
    {
        "$project": {
            "numberOfEntries": {
                "$size": {
                    "$setDifference": [
                        {
                            "$map": {
                                "input": "$notifications",
                                "as": "items",
                                "in": {
                                    "$cond": [
                                        { "$and": [
                                            { "$eq": [ "$$items.enabled", true ] },
                                            { "$setIsSubset": [ [ "NG3" ], "$$items.groups" ] }
                                        ] },
                                        "$$items",
                                        false
                                    ]
                                }
                            }
                        },
                        [false]
                    ]
                }
            }
        }
    }
];

db.collection.aggregate(pipeline);

对于没有上述运算符的旧 MongoDB 版本,请考虑使用 $match , $unwind $group 运营商实现同样的目标:

var pipeline = [
    { "$match": { "notifications.enabled": true, "notifications.groups": "NG3" } },
    { "$unwind": "$notifications" },
    { "$match": { "notifications.enabled": true, "notifications.groups": "NG3" } },
    {
        "$group": {
            "_id": "$_id",
            "numberOfEntries": { "$sum": 1 }
        }
    }
];
db.collection.aggregate(pipeline);

关于mongodb - 计算符合给定条件的子文档,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37480320/

相关文章:

Mongodb应用基于条件的聚合方法

mongodb - 克隆并重命名 Mongodb 中子文档数组的字段

javascript - 如何获取 mongodb 聚合上所有条目的对象数组的值重复计数

node.js - Mongodb 关系 : Posts and Comments (ref v sub-documents)

mongodb - 从Mongodb Golang中的对象获取查询的元素

node.js - 多语言 NodeJs API

Mongodb Schema考虑子文档以避免多次读取

java - 相当于 MongoCursor 快照的 MongoDB Java 驱动程序

node.js - 如何通过 $lookup 对 'joined' 集合执行 $text 搜索?

Mongodb 更新管道更新嵌套数组中元素的字段