如何过滤子文档数组?

时间:2016-06-03 03:23:04

标签: mongodb mongodb-query aggregation-framework

我的文档结构如下:

{ 
"_id" : ObjectId("564d2702d4c68225cb00726f"), 
"list" : [
    {
        "a" : NumberInt(1), 
        "test" : "public"
    }, 
    {
        "a" : NumberInt(2), 
        "test" : "public"
    }, 
    {
        "a" : NumberInt(3), 
        "test" : "public"
    }, 
    {
        "a" : NumberInt(4), 
        "test" : "public"
    }, 
    {
        "a" : NumberInt(5), 
        "test" : "public"
    }
],
"other_fields": ""}

我可以过滤in(1,5)

的子文档

我希望结果低于

{
"_id" : ObjectId("564d2702d4c68225cb00726f"),
"list" : [
    {
        "a" : NumberInt(1),
        "test" : "public"
    },
    {
        "a" : NumberInt(5),
        "test" : "public"
    }
]}

我尝试使用$elemMatch,但是当我使用$in时,发生了错误。

2 个答案:

答案 0 :(得分:3)

从MongoDB 3.2开始,我们可以使用$filter运算符来有效地实现此目的。在$filter的条件表达式中,我们需要使用$setIsSubset运算符来检查给定值是否在数组中。这主要是因为我们无法在$in阶段使用$project查询运算符。

db.collection.aggregate([
    { "$project": { 
        "list": { 
            "$filter": { 
                "input": "$list", 
                "as": "lst", 
                "cond": { "$setIsSubset": [ [ "$$lst.a" ], [ 1, 5 ] ] }
            } 
        } 
    }}
])

从MongoDB 3.0.x开始,您需要使用$map运算符和$setDifference运算符来实现另一种效率较低的方法。

db.collection.aggregate([
    { "$project": { 
        "list": { 
            "$setDifference": [ 
                { "$map": { 
                    "input": "$list", 
                    "as": "lst", 
                    "in": { 
                        "$cond": [
                            { "$setIsSubset": [ [ "$$lst.a" ], [ 1, 5 ] ] },
                            "$$lst",
                            false
                        ] 
                    } 
                }}, 
                [false] 
            ]
        }
    }}
])

答案 1 :(得分:0)

尝试以下查询: -

db.collection.aggregate([
{ 
    "$match": {
       $or[{ "list.a": NumberInt(1)}, {{ "list.a": NumberInt(5)}}]
    }
},
{
    "$project": {
        "list": {
            "$setDifference": [
                {
                    "$map": {
                        "input": "$list",
                        "as": "o",
                        "in": {
                            "$cond": [
                                {  
                                     $or[{ "list.a": NumberInt(1)}, 
                                         {{ "list.a": NumberInt(5)}}]
                                },
                                "$$o",
                                false
                            ]
                        }
                    }
                },
                [false]
            ]
        }
    }
}
])

通过使用查询结果将是: -

{
    "_id" : ObjectId("564d2702d4c68225cb00726f"),
    "list" : [
    {
        "a" : NumberInt(1),
        "test" : "public"
    },
    {
        "a" : NumberInt(5),
        "test" : "public"
    }
]}
相关问题