返回给定字段所在的数组子集

时间:2016-05-15 17:31:53

标签: php mongodb mongodb-query aggregation-framework mongodb-php

我想过滤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")
        }
    ]

2 个答案:

答案 0 :(得分:1)

根据上述说明,请尝试执行以下查询

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

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

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

答案 1 :(得分:1)

最佳方法是使用聚合框架在MongoDB 3.2中。您只需要投影文档并使用$filter运算符返回符合条件的“类别”数组的子集,但要执行此操作,您需要使用$ifNull运算符给出“默认值” “缺少该字段的所有子文档中的”父“字段的值,然后使用cond表达式中的$ne来确定应该在子集中包含给定元素的位置。

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

从版本3.0开始,您需要一种不同的方法。相反,您需要使用$map运算符返回给定元素(如果它符合您的条件)或false然后使用$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) 
                )
            )
        ))
    )
)