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

Mongodb how can I query a subset of an array for a specific document

我想 运行 查询 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 功能做点什么。我已经能够匹配我想要的文档,但是我怎样才能在数组上进行子查询呢?我尝试使用 $elemMatch,但只有 return 是数组中与日期范围匹配的第一项。

当我查询 ObjectID(23412351346435) 和日期范围 2015-01-12 到 2015-01-13 时要清楚,我希望它 return this;

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

您可以使用 $unwind 运算符。它允许您在文档中获取一个数组,并使用每个数组元素克隆该文档。然后你就可以在场上比赛了。如有必要,您可以使用 $group 将文档备份。

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

请注意,$unwind 对于大型文档集来说很慢,对于多个数组来说是组合的。这是 Mongo 2.4.x 的唯一选择。重新排列数据可能会更好,这样您就没有数组。

如您所料,您可以使用 aggregation 来获得您要查找的结果。您需要在 aggregation pipeline 中执行的步骤如下。

  1. Match你想要的文件。 (我已经在 _id 之前完成了)。
  2. Unwind list 数组。
  3. 使用范围查询匹配您要查找的日期。
  4. Group _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" }}
    }}
]);