不能在MongoDB查询中包含带有$ project运算符的字段

时间:2016-06-30 13:19:58

标签: mongodb mongodb-query aggregation-framework

在我的MongoDB数据库中,我有一个名为test的集合,如下所示:

{
    "_id" : ObjectId("5774f2807f93c094a6691506"),
    "name" : "jack",
    "city" : "LA",
    "age" : 30.0,
    "cars" : 0
}

{
    "_id" : ObjectId("5774f2be7f93c094a6691507"),
    "name" : "jack",
    "city" : "LA",
    "age" : 40.0,
    "cars" : 0
}

{
    "_id" : ObjectId("5774f2ed7f93c094a6691508"),
    "name" : "peter",
    "city" : "London",
    "age" : 35.0,
    "cars" : 1
}

我做了一个查询,按名称和城市对人进行分组,只显示每个组的最旧元素。此外,它只显示至少有一辆车的家伙。查询如下所示:

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

                {
                    "$match":{"cars":{$ne:0}}
                },
                {
                    "$group": { "_id": { name: "$name", city: "$city" }, "age":{$max:"$age"}}
                }
                ,
                {
                    "$project":{"age":1, "name":"$_id.name", "city":"$_id.city", "cars":true}
                }
       ] )

执行上述查询后,我得到以下结果:

{
    "_id" : {
        "name" : "peter",
        "city" : "London"
    },
    "age" : 35.0,
    "name" : "peter",
    "city" : "London"
}

这是正确的,因为彼得是唯一一个拥有汽车的人。问题是它没有显示"汽车"领域。正如您在查询中看到的那样,有一个$ project运算符和" cars" field设置为true。所以它应该显示出来。

3 个答案:

答案 0 :(得分:1)

在分组阶段添加汽车有帮助吗?我假设你需要数数。

"$group": {
  "_id": { name: "$name", city: "$city" },
  "age": { $max:"$age" }
  "cars": { $sum:"$cars" }
}

项目阶段的输入是分组阶段的输出。在原始查询中,此输入中没有可用的汽车字段。

答案 1 :(得分:0)

一个解决方案可能是" $ push"在对数据进行分组时将汽车分成阵列。

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

                {
                    "$match":{"cars":{$ne:0}}
                },
                {
                    "$group": { "_id": { name: "$name", city: "$city" }, 
                                       cars : {$push : "$cars"}, "age":{$max:"$age"}}
                }
                ,
                {
                    "$project":{"age":1, "name":"$_id.name", "city":"$_id.city", "cars":true}
                }
       ] )

答案 2 :(得分:0)

它未显示,因为它未在上一个管道阶段创建。要了解聚合管道的工作原理,请像处理任何数据库系统一样处理聚合操作。

$group 管道运算符类似于SQL的GROUP BY子句。在SQL中,除非我们使用任何聚合函数,否则不能使用GROUP BY

同样,你也必须在MongoDB中使用聚合函数。在这种情况下,要生成汽车字段,您必须使用 $first 运算符返回组中的顶级文档字段。

当进入 $group 管道步骤的文档被排序时,这很有效,因此需要在 $sort 管道之前<强> $group 订购。然后,您可以将 $first 运算符应用于有序组以获得最大值(这实际上是有序组中的顶级文档及其相应的汽车值)。

返回所需字段的正确管道如下所示:

db.test.aggregate([
    { "$match": { "cars": { "$ne": 0 } } },
    { "$sort": { "name": 1, "city": 1, "age": -1 } }
    {
        "$group": { 
            "_id": { "name": "$name", "city": "$city" }, 
            "age": { "$first": "$age" } ,
            "cars": { "$first": "$cars" } 
        }
    },
    {
        "$project": {
            "age": 1, 
            "cars": 1,
            "_id": 0,
            "name": "$_id.name", 
            "city": "$_id.city"             
        }
    }
])