如何使用聚合框架在mongodb中对动态属性进行分组?

时间:2013-07-23 15:33:13

标签: mongodb mongoose aggregation-framework

我正在使用mongodb FAQ中的以下架构:

{
  attrib : [
        { k: "color", v: "red" },
        { k: "shape", v: "rectangle" },
        { k: "color", v: "blue" },
        { k: "avail", v: true }
       ]
}

如何对收集进行分组和计数,例如用“颜色”?如果可能的话,我更愿意使用聚合框架而不是map reduce。

我的结果应如下所示:

[
    {
        v: "blue",
        count: 5
    },
    {
        v: "red",
        count: 2
    },
    {
        v: "black",
        count: 52
    }
]

1 个答案:

答案 0 :(得分:2)

这非常简单,我们需要通过以下方式进行展开,匹配和分组:

db.so.aggregate( [
    { $unwind : '$attrib' },
    { $match: { 'attrib.k' : 'color' } },
    { $group: { _id: '$attrib.v', count: { '$sum': 1 } } }
] );

Unwind将“attrib”数组炸成每个数组元素一个文档:

{
    "result" : [
        {
            "_id" : ObjectId("51eeb9f2812db9ff4412f132"),
            "attrib" : {
                "k" : "color",
                "v" : "red"
            }
        },
        {
            "_id" : ObjectId("51eeb9f2812db9ff4412f132"),
            "attrib" : {
                "k" : "shape",
                "v" : "rectangle"
            }
        },
        {
            "_id" : ObjectId("51eeb9f2812db9ff4412f132"),
            "attrib" : {
                "k" : "color",
                "v" : "blue"
            }
        },
        {
            "_id" : ObjectId("51eeb9f2812db9ff4412f132"),
            "attrib" : {
                "k" : "avail",
                "v" : true
            }
        }
    ],
    "ok" : 1
}

匹配然后删除所有非颜色项目:

{
    "result" : [
        {
            "_id" : ObjectId("51eeb9f2812db9ff4412f132"),
            "attrib" : {
                "k" : "color",
                "v" : "red"
            }
        },
        {
            "_id" : ObjectId("51eeb9f2812db9ff4412f132"),
            "attrib" : {
                "k" : "color",
                "v" : "blue"
            }
        }
    ],
    "ok" : 1
}

小组终于回来了:

{
    "result" : [
        {
            "_id" : "blue",
            "count" : 1
        },
        {
            "_id" : "red",
            "count" : 1
        }
    ],
    "ok" : 1
}

(以上所有输出仅来自您的单个样本文件)