如果我有如下收藏品:
db.cafe.insert({name: "Cafe1", customers: [{name: "David", foods: [{name : "cheese"}, {name: "beef"}]}, {name: "Bill", foods: [{name: "fish"}]} ]})
db.cafe.find().pretty()
{
"_id" : ObjectId("54f5ae58baed23b7a34fccb6"),
"name" : "Cafe1",
"customers" : [
{
"name" : "David",
"foods" : [
{
"name" : "cheese"
},
{
"name" : "beef"
}
]
},
{
"name" : "Bill",
"foods" : [
{
"name" : "fish"
}
]
}
]
}
如何为名为“David”的人提取仅包含食物对象的数组。 期望的产出只是食物的一系列,即:
[{name: "cheese"}, {name: "beef"}]
我尝试了一个聚合管道来解开咖啡馆的顾客,然后根据名称进行匹配然后预测食物,例如:
db.cafe.aggregate( [{$unwind : "$customers"}, {$match : {"customers.name": "David"}}, {$project : {"customers.foods": 1, _id : 0}
}] ).pretty()
{
"customers" : {
"foods" : [
{
"name" : "cheese"
},
{
"name" : "beef"
}
]
}
}
这似乎接近于预期的结果,但是,我留下的问题是我想要的食物被引用为属性customers.foods下的数组。我希望结果直接是:
[
{
"name" : "cheese"
},
{
"name" : "beef"
}
]
有没有办法可以实现所需的输出?
答案 0 :(得分:2)
你的投射错误。
db.cafe.aggregate( [
{ "$match" : { "customers.name": "David" }},
{ "$unwind" : "$customers" },
{ "$project" : { "foods": "$customers.foods", "_id": 0 }}
])
<强>输出强>
{ "foods" : [ { "name" : "cheese" }, { "name" : "beef" } ] }
答案 1 :(得分:1)
您还可以通过常规查询得到(非常非常接近)您想要的输出:
> db.cafe.find({ "customers.name" : "David" }, { "customers.$.foods" : 1, "_id" : 0 })
{ "customers" : [ { "name" : "David", "foods" : [ { "name" : "cheese" }, { "name" : "beef" } ] } ] }
客户将是一个仅包含name : "David"
的第一个对象的数组。您应该更喜欢这种聚合方法,因为它的性能要高得多。您可以在客户端代码中提取foods
数组。