2015-03-03 100 views
0

如果我有一个集合,如下所示:MongoDB的聚集投影

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" 
       } 
      ] 
     } 
    ] 
} 

我如何可以提取只包含人称为“万人迷”的食物对象的数组。 所需的输出仅仅是食物的阵列,即:

[{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

我认为你应该改变你的项目如下 '{“$ project”:{“_ id”:0,“food”:“$ customers.foods”}}' – Yogesh 2015-03-03 13:12:24

回答

2

你正在做你的投影错误。

db.cafe.aggregate([ 
    { "$match" : { "customers.name": "David" }}, 
    { "$unwind" : "$customers" }, 

    { "$project" : { "foods": "$customers.foods", "_id": 0 }} 
]) 

输出

{ "foods" : [ { "name" : "cheese" }, { "name" : "beef" } ] } 
+0

谢谢,这很接近但不完全是什么我在之后。我得到的麻烦是在我的服务器端代码中,我正在使用Object Mapper将bson转换为Java对象。我试图避免创建另一个专用于此结果集的对象并重用现有的对象。但它似乎不可能。不过谢谢你的建议,它确实很接近。 – 2015-03-04 09:22:07

1

您还可以得到(东西非常非常接近)与常规查询您所需的输出:

> db.cafe.find({ "customers.name" : "David" }, { "customers.$.foods" : 1, "_id" : 0 }) 
{ "customers" : [ { "name" : "David", "foods" : [ { "name" : "cheese" }, { "name" : "beef" } ] } ] } 

客户将是包含name : "David"的第一个对象的数组。您应该更喜欢这种聚合方法,因为它性能更高。您可以在客户端代码中提取foods数组。

+0

那么,如果实际上并没有按照要求选择该领域,那么注意到“客户,食品”这一点会有什么意义呢?这就像是说“不要打扰投射领域,因为你可以在客户代码中删除你不想要的领域”。我不明白这是如何提供任何价值的。 – 2015-03-04 00:34:24

+0

谢谢。我认为对于我的实际用例,我将需要聚合管道(因为我正在过滤一个数组,其中包含各种标准以及应用排序和限制),因为它并不像这个问题所指出的那样直截了当。我正在使用我正面临的问题的简化版本。 – 2015-03-04 09:24:22