Return 存在给定字段的数组子集

Return a subset of array where a given field is present

我想过滤 Categories 嵌入式数组以仅获取具有 parent 键的数组。

{
    "_id": ObjectId("5737283639533c000978ae71"),
    "name": "Swiss",
    "Categories": [
        {
            "name": "Management",
            "_id": ObjectId("5738982e39533c00070f6a53")
        },
        {
            "name": "Relations",
            "_id": ObjectId("5738984a39533c000978ae72"),
            "parent": ObjectId("5738982e39533c00070f6a53")
        },
        {
            "name": "Ambiance",
            "_id": ObjectId("57389bed39533c000b148164")
        }
    ]
}

我试过 find 但没有成功。 经过一些研究,它似乎可以通过聚合命令完成,但我不喜欢它的工作方式,我更愿意只使用 find 命令。

此外,我问自己,就性能而言,将每个类别存储在一个新集合中是否更好,是吗?

编辑,我想得到这样的东西作为查找输出:

    [
        {
            "name": "Relations",
            "_id": ObjectId("5738984a39533c000978ae72"),
            "parent": ObjectId("5738982e39533c00070f6a53")
        }
    ]

作为根据上述描述的解决方案,请尝试执行以下查询

db.mycoll.find({Categories:{$elemMatch:{parent:{$exists:true}}}},

{Categories:{$elemMatch:{parent:{$exists:true}}}})

以上示例使用 $elemMatch 运算符过滤嵌入文档中的元素。

最佳方法是在 MongoDB 3.2 中使用聚合框架。您所需要的只是投影您的文档并在 cond 表达式中使用 $filter operator to return a subset of the "Categories" array that match your criteria, but to do this you will need to use $ifNull operator give a "default" value to the "parent" field in all those sub-documents where that field is missing then use the $ne 来确定给定元素应包含在子集中的何处。

db.collection.aggregate([
    { "$project" : { 
        "_id": 0, 
        "Categories": { 
            "$filter": { 
                "input": "$Categories", 
                "as": "catg", 
                "cond": { 
                    "$ne": [
                        { "$ifNull": [ "$$catg.parent", false ] }, 
                        false
                    ]
                }
            }
        }
    }}
])

从 3.0 版开始,您需要一种不同的方法。相反,您需要使用 $map operator to return a give element if it matches your criteria or false then use the $setDifference 运算符来过滤掉返回数组中等于 false 的所有元素。当然 $setDifference 只要被过滤的数据是“唯一的”就可以了。

db.collection.aggregate([
    { "$project" : { 
        "_id": 0, 
        "Categories": { 
            "$setDifference": [ 
                { "$map": { 
                    "input": "$Categories", 
                    "as": "catg", 
                    "in": { 
                         "$cond": [ 
                             { "$ne": [
                                 { "$ifNull": [ "$$catg.parent", false ] },
                                 false
                             ]}, 
                             "$$catg", 
                             false
                        ]}
                    }
                }, 
                [ false ] 
            ]
        }
    }}
])

PHP 中的翻译给出:

db.collection.aggregate(
    array(
        array("$project" => array(
            "_id" => 0, 
            "Categories" => array( 
                "$filter" => array(
                    "input" => "$Categories", 
                    "as" => "catg", 
                    "cond" => array(
                         "$ne" => array(
                             array("$ifNull" => array("$$catg.parent", false), 
                         false
                    )
                )
              )  
          )
      ))
   )
)

还有这个:

db.collection.aggregate(
    array(
        array("$project" => array( 
            "_id" => 0, 
            "Categories" => array( 
                "$setDifference" => array(
                    "$map" => array( 
                        "input" => "$Categories", 
                        "as" => "catg", 
                        "in" => array( 
                            "$cond" => array(
                                "$ne" => array(
                                     array("$ifNull" => array( "$$catg.parent", false ) ),
                                     false
                            ), 
                            "$$catg", 
                            false
                        )
                    ),
                    array(false) 
                )
            )
        ))
    )
)