MongoDB中的“结构化”分组查询

时间:2015-12-12 11:49:32

标签: mongodb aggregation-framework

我有以下项目集合:

[{
    "_id": 1,
    "manufactureId": 1,
    "itemTypeId": "Type1"
},
{
    "_id": 2,
    "manufactureId": 1,
    "itemTypeId": "Type2"
},
{
    "_id": 3,
    "manufactureId": 2,
    "itemTypeId": "Type1"
}]

我想创建一个查询,该查询将返回每个制造商在以下结构中具有的每种商品类型的商品数量(或类似内容):

[
    {
        _id:1, //this would be the manufactureId
        itemsCount:{
            "Type1":1, //Type1 items count
            "Type2":1  //...
        }
    },
    {
        _id:2,
        itemsCount:{
            "Type1":1
        }
    }
]

我曾尝试使用聚合框架,但我无法弄清楚是否有办法用它创建“结构化”组查询。 我可以通过后处理这个简单的聚合查询结果轻松实现所需的结果:

db.items.aggregate([{$group:{_id:{itemTypeId:"$itemTypeId",manufactureId:"$manufactureId"},count:{$sum:1}}}])

但如果可能的话,我不想对结果进行后期处理。

1 个答案:

答案 0 :(得分:1)

数据保留数据

我宁愿使用这个查询,我相信,它会为您提供最接近您想要的数据结构,而无需后期处理。

查询

db.items.aggregate(
{
    $group:
    {
        _id:
        {
            itemTypeId: "$itemTypeId",
            manufactureId: "$manufactureId"
        },
        count:
        {
            $sum: 1
        }
    },
},
{
    $group:
    {
        _id: "$_id.manufactureId",
        itemCounts:
        {
            "$push":
            {
                itemTypeId: "$_id.itemTypeId",
                count: "$count"
            }
        }
    }
})

输出

{
    "_id" : 1,
    "itemCounts" : [
        {
            "itemTypeId" : "Type1",
            "count" : 1
        },
        {
            "itemTypeId" : "Type2",
            "count" : 1
        }
    ]
},
{
    "_id" : 2,
    "itemCounts" : [
        {
            "itemTypeId" : "Type1",
            "count" : 1
        }
    ]
}

数据转换为对象字段

这实际上是一种我一般不会建议的方法。在您的应用程序中管理起来比较困难,因为不同对象之间的字段名称将不一致,您不会事先知道要预期的对象字段。如果您使用强类型语言,这将是一个关键点 - 自动数据绑定到您的域对象将变得不可能。

无论如何,获得所需数据结构的唯一方法是应用后处理。

查询

db.items.aggregate(
{
    $group:
    {
        _id:
        {
            itemTypeId: "$itemTypeId",
            manufactureId: "$manufactureId"
        },
        count:
        {
            $sum: 1
        }
    },
},
{
    $group:
    {
        _id: "$_id.manufactureId",
        itemCounts:
        {
            "$push":
            {
                itemTypeId: "$_id.itemTypeId",
                count: "$count"
            }
        }
    }
}).forEach(function(doc) {
    var obj = {
        _id: doc._id,
        itemCounts: {}
    };

    doc.itemCounts.forEach(function(typeCount) {
        obj.itemCounts[typeCount.itemTypeId] = typeCount.count;
    });

    printjson(obj);
})

输出

{ "_id" : 1, "itemCounts" : { "Type1" : 1, "Type2" : 1 } }
{ "_id" : 2, "itemCounts" : { "Type1" : 1 } }