在我的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。所以它应该显示出来。
答案 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"
}
}
])