Mongo:聚合获取hashmap

时间:2015-06-11 17:07:03

标签: mongodb mongodb-query aggregation-framework

我有集合db.problems。每个文档都包含嵌套的areacategory个对象。文档的例子:

{
    _id: 1,
    text: 'Hello',
    area: {_id: 23, title: 'Area 61'},
    category: {_id: 12, title: 'Just a category'}
}

我正在尝试按类别计算每个区域的问题,并得到类似的结果:

[
    {
        area: {_id: 2, title: 'Area 61'},
        categoriesStats: {
            12: {title: 'Just a category', problemCount: 123},
            42: {title: 'Another category', problemCount: 11}
        }
   },
   {...}
]

主要的是categoriesStats必须是哈希(将类别的id作为键)

我现在的目标是什么:

db.problems.aggregate([
    {$group: {
        _id: {areaId: '$area._id', categoryId: '$category._id'},
        problemCount: {$sum: 1},
        area: {$first: '$area'},
        category: {$first: '$category'}
    }},
    {$group: {
        _id: '$_id.areaId',
        area: {$first: '$area'},
        categoriesStats: {
            $push: {
                problemCount: '$problemCount',
                category: '$category'
            }
        }
    }},
    {$project: {_id: 0, area: 1, categoriesStats: 1}}
])

此查询的结果:

{
    "result": [ 
        {
            "area": {"_id": 37, "name": "Some area"},
            "categoriesStats": [
                {
                    "problemCount": 1,
                    "category": {"_id": 4, "title": "Just a cat"}
                },
                {
                    "problemCount": 1,
                    "category": {"_id": 3, "title": "Misc"}
               }
            ]
        }, 
        {
            "area": {"_id": 36, "name": "wow such area"},
            "categoriesStats": [ 
                {
                    "problemCount": 1,
                    "category": {"_id": 4, "title": "Just a cat"}
                }, 
                {
                    "problemCount": 2,
                    "category": {"_id": 3, "title": "Misc"}
                }
            ]
        }
    ],
    "ok": 1
}

正如您所看到的,我已经设法获得了几乎所需的结果,但我无法将categoriesStats作为哈希值。

我在$project阶段尝试过查询 {$project: {'$category._id': '$categories'},但

  

“$ project的顶层不允许使用$表达式”

此外,我也试图像这样预定义查询:

3是某类别的_id

{$group: ...},
{$project: {
 'categoriesStats.3': {$cond: [{$eq: ['$category._id', 3]}, '$category', null]}}, 
 //Same field for every category _id
{$group: ...}

但在这种情况下,我无法通过$group阶段

获取此哈希值

所以,问题是,无论如何要以 hashmap 形式获取categoriesStats吗?

1 个答案:

答案 0 :(得分:2)

您可以使用游标方法 forEach() 修改聚合的结果,以迭代游标并访问文档,如下例所示:

var cur = db.problems.aggregate([
    {$group: {
        _id: {areaId: '$area._id', categoryId: '$category._id'},
        problemCount: {$sum: 1},
        area: {$first: '$area'},
        category: {$first: '$category'}
    }},
    {$group: {
        _id: '$_id.areaId',
        area: {$first: '$area'},
        categoriesStats: {
            $push: {
                problemCount: '$problemCount',
                category: '$category'
            }
        }
    }},
    {$project: {_id: 0, area: 1, categoriesStats: 1}}
]),
results = [];

cur.forEach(function (res){
    var obj = { 
        "categoriesStats": {} 
    };
    var category = {};
    obj.area = res.area;
    res.categoriesStats.forEach(function(c){
        var cat = {};        
        cat["title"] = c.category.title;
        cat["problemCount"] = c.problemCount;        
        obj["categoriesStats"][c.category._id.toString()] = cat;
    });

    results.push(obj);
});

查看下面的演示



var cur = {
    "result": [ 
        {
            "area": {"_id": 37, "name": "Some area"},
            "categoriesStats": [
                {
                    "problemCount": 1,
                    "category": {"_id": 4, "title": "Just a cat"}
                },
                {
                    "problemCount": 1,
                    "category": {"_id": 3, "title": "Misc"}
               }
            ]
        }, 
        {
            "area": {"_id": 36, "name": "wow such area"},
            "categoriesStats": [ 
                {
                    "problemCount": 1,
                    "category": {"_id": 4, "title": "Just a cat"}
                }, 
                {
                    "problemCount": 2,
                    "category": {"_id": 3, "title": "Misc"}
                }
            ]
        }
    ],
    "ok": 1
};
var results = [];
cur.result.forEach(function (doc){
    var obj = { 
        "categoriesStats": {} 
    };
    var category = {};
    obj.area = doc.area;
    doc.categoriesStats.forEach(function(c){
        var cat = {};        
        cat["title"] = c.category.title;
        cat["problemCount"] = c.problemCount;        
        obj["categoriesStats"][c.category._id.toString()] = cat;
    });
    
    results.push(obj);
});

pre.innerHTML = JSON.stringify(results);

<pre id="pre"></pre>
&#13;
&#13;
&#13;

相关问题