Mongodb如何查询特定文档的数组子集

我想运行一个查询来select特定的文件。 然后在每个文档上打开一个子文档数组并运行一个查询来过滤这些子文档。

例:

{ "_id" : ObjectID(23412351346435), "list" : [ {date: ISODate(2015-01-12T00:00:00.000Z), name: "Jan 12"}, {date: ISODate(2015-01-13T00:00:00.000Z), name: "Jan 13"}, {date: ISODate(2015-01-14T00:00:00.000Z), name: "Jan 14"} ] } 

我猜测我可以用Mongo的aggregate函数做一些事情。 我已经能够匹配我想要的文件,但我怎么能得到一个子查询进入arrays? 我尝试使用$elemMatch但只返回匹配date范围的数组中的第一个项目。

当我查询ObjectID(23412351346435)和date范围2015-01-12到2015-01-13要清楚我希望它返回这个;

 { "_id" : ObjectID(23412351346435), "list" : [ {date: ISODate(2015-01-12T00:00:00.000Z), name: "Jan 12"}, {date: ISODate(2015-01-13T00:00:00.000Z), name: "Jan 13"} ] } 

正如你所猜测的,你可以使用aggregation来获得你正在寻找的结果。 您需要在您的聚合pipe道中执行以下步骤。

  1. 匹配你想要的文件。 (我已经在这里做了_id )。
  2. 展开list数组。
  3. 使用范围查询匹配您正在查找的date。
  4. 将文件分组回到_id

你的查询应该是这样的:

 db.collection.aggregate([ { "$match": { "_id": ObjectId("54ef8b0acfb269d664de0b48")} }, { "$unwind": "$list" }, { "$match": { "list.date": { $gte: ISODate("2015-01-12T00:00:00.000Z"), $lte: ISODate("2015-01-13T00:00:00.000Z") } }}, { "$group": { "_id": "$_id", "list": { "$push": { "date": "$list.date", "name": "$list.name" }} }} ]); 

您可以使用$ unwind运算符。 它允许你在文档中获取一个数组,然后用每个数组元素克隆该文档。 那么你可以在现场比赛。 如有必要,您可以使用$ group将文档重新打包。

 [ {$match:{...}}, {$unwind:"myfield"}, {$match:{"myfield.name":"Jan 12"}}, {$group:{ _id:"$id", "myfield":{$push:"$myfield"} }} ] 

请注意,对于大型文档集,$ unwind是缓慢的,对于多个数组则是组合式的。 这是Mongo 2.4.x真正唯一的select。 重新排列数据可能会更好,因此您没有数组。