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

时间:2015-02-26 20:55:10

标签: node.js mongodb aggregation-framework

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

示例:

{
  "_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,但只返回数组中与日期范围匹配的第一项。

当我查询ObjectID(23412351346435)和日期范围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"}
   ]
}

2 个答案:

答案 0 :(得分:1)

您可以使用$unwind运算符。它允许您在文档中获取数组,并使用每个数组元素克隆该文档。然后你可以匹配该字段。如有必要,您可以使用$ group来备份文档。

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

请注意,$ unwind对于大型文档集来说很慢,对于多个阵列来说是组合式的。这是你真正拥有Mongo 2.4.x的唯一选择。通过重新排列数据可以更好地为您提供服务,以便您没有阵列。

答案 1 :(得分:0)

正如您所猜测的,您可以使用aggregation来获得您想要的结果。 aggregation pipeline中需要的步骤如下:

  1. Match您想要的文件。 (我已经_id)在这里做了。
  2. Unwind list数组。
  3. 使用范围查询匹配您要查找的日期。
  4. Group文件由_id返回。
  5. 您的查询应如下所示:

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