在MondoDB聚合中没有特定字段的过滤器数组元素

时间:2019-11-13 11:57:00

标签: mongodb mongodb-query aggregation-framework

我在mongodb中有一个people集合,如下所示。

MongoDB版本:4.0.13

{
    "_id" : ObjectId("5dcbeb97e184e0f527c6a3e7"),
    "name" : "nithin",
    "age" : 35.0,
    "addresses" : [ 
        {
            "street" : "xyz",
            "city" : "Tvm"
        }, 
        {
            "street" : "pqr",
            "city" : "KLM"
        }, 
        {
            "street" : "abc"
        }
    ]
}


{
    "_id" : ObjectId("5dcbebe4e184e0f527c6a3e8"),
    "name" : "akash",
    "age" : 21.0,
    "addresses" : [ 
        {
            "street" : "lon",
            "city" : "London"
        }, 
        {
            "street" : "par",
            "city" : "paris"
        }, 
        {
            "street" : "abc"
        }
    ]
}

我需要过滤掉所有没有city属性的地址。我到目前为止所取得的成就是

db.getCollection('People').aggregate([

    {
        $project:
        {
            "name":1,
            "age":1,
            "addresses":
            {
                $filter:
                {
                    input:"$addresses",
                    as:"address",
                    cond:{$not:["$$address.city"]}
                }
            }

        }   


    }

])

结果:我得到的所有地址都没有city属性(这与我需要的完全相反)。我找不到SO的任何帮助。如何否定not结果

我也尝试过

        $filter:
        {
            input:"$addresses",
            as:"address",
            cond:{"$exists":["$$address.city":true]}
        }

结果:

  

错误:第14行:意外的令牌:

1 个答案:

答案 0 :(得分:0)

在这种情况下,不必进行汇总。您只需将find与$elemMatch运算符配合使用:

db.people.find({
    addresses: {$elemMatch : {city: {$exists: false}}}
})

但是,如果要使用聚合,则可以对同一查询进行匹配:

db.people.aggregate([
    {$match: {addresses: {$elemMatch : {city: {$exists: false}}}}}
])

或者,您也可以像下面所示那样进行操作,但是我认为elemMatch的运行速度会更快:

db.people.aggregate([
{$unwind: '$addresses'},
{$match: {"addresses.city" : {$exists: false}}}
{$group: { _id : '$_id', addresses: {$addToSet: "$addresses"}}}
])