聚合请求MongoDB

时间:2013-07-19 10:49:04

标签: mongodb hashmap aggregation-framework

我想在带有条件的集合列表中获取多个字段。我尝试了一个聚合请求,但是我有一个错误。

我的要求

db.people.aggregate({$match:{createdDate:{$exists:true},"ad":"noc2"}},{$group:{value2:$value2}});

我的杰森:


    db.test.findOne();
{
        "_id" : ObjectId("51e7dd16d2f8db27b56ea282"),
        "ad" : "noc2",
        "list" : {
                "p45" : {
                        "id" : "p45",
                        "date" : ISODate("2014-01-01T12:18:30.568Z"),
                        "value3" : 21,
                        "value1" : 100,
                        "value2" : 489
                },
                "p6" : {
                        "id" : "p6"
                        "date" : ISODate("2013-07-18T12:18:30.568Z"),
                        "value3" : 21,
                        "value1" : 100,
                        "value2" : 489
                },
                "p4578" : {
                       "id" : "4578"
                        "date" : ISODate("2013-07-18T12:18:30.568Z"),
                        "value3" : 21,
                        "value1" : 100,
                        "value2" : 489
                }
        }
}

我想得到这个json,例如,结果:

{id:p45,value:587},{id:p4578,value:47},{id:p6,value:2}

1 个答案:

答案 0 :(得分:5)

您的示例文档和聚合有几个问题:

  • 示例文档与您的聚合查询不匹配,因为您在createdDate字段现有
  • 上匹配
  • $group() operator适用于文档级别,需要_id字段进行分组
  • 您的list字段是嵌入式文档,而不是数组
  • 除了格式化之外,没有明显的方法将样本值与您正在寻找的计算结果相关联

以下是调整后的示例文档,其中list为数组,并且每个项目的一些唯一值恰好与您提到的value数字相加:

db.people.insert({
        "ad" : "noc2",
        "createdDate" : ISODate(),
        "list" : [
                {
                        "id" : "p45",
                        "date" : ISODate("2014-01-01T12:18:30.568Z"),
                        "value3" : 21,
                        "value1" : 77,
                        "value2" : 489
                },
                {
                        "id" : "p6",
                        "date" : ISODate("2013-07-18T12:18:30.568Z"),
                        "value3" : 20,
                        "value1" : 20,
                        "value2" : 7
                },
                {
                       "id" : "4578",
                        "date" : ISODate("2013-07-18T12:18:30.568Z"),
                        "value3" : 21,
                        "value1" : 300,
                        "value2" : -319
                }
        ]
})

您现在可以使用$unwind operator来提取匹配的子文档。

目前的问题描述尚不清楚您尝试实现的$group操作以及您是否确实需要$group

以下是使用聚合框架$add(总计)每个列表项的三个值的示例:

db.people.aggregate(

    // Find relevant docs (can use index if available)
    { $match: {
        createdDate: { $exists:true },
        "ad":"noc2"
    }},

    // Convert list array to stream of documents
    { $unwind: "$list" },

    // Add  (value1, value2, value3) for each list item 
    { $project: {
        _id: "$list.id",
        value: { $add: [ "$list.value1", "$list.value2", "$list.value3"] }
    }}
);

示例输出:

{
    "result" : [
        {
            "_id" : "p45",
            "value" : 587
        },
        {
            "_id" : "p6",
            "value" : 47
        },
        {
            "_id" : "4578",
            "value" : 2
        }
    ],
    "ok" : 1
}

请注意,我仅使用此示例的单个文档进行聚合,输出将是list数组中每个项目的一个结果文档。

在实际使用中,您可能希望按文档$group或其他一些标准向_id添加其他聚合步骤,具体取决于您尝试实现的结果。