【问题标题】:Mongo: get hashmap in aggregateMongo:汇总获取哈希图
【发布时间】:2015-06-11 17:07:03
【问题描述】:

我收藏了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必须是一个hash(以category的id为key)

我现在想到的:

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

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    您可以通过使用游标方法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>

    【讨论】:

    • 但这只是javascript操作。是不是有一种 mongo 方法可以做到这一点?
    • @Danielo515 不幸的是,虽然有提议的运营商可以做到这一点,但没有,请查看stackoverflow.com/questions/37052551了解更多详细信息。
    猜你喜欢
    • 1970-01-01
    • 2016-05-26
    • 2021-12-11
    • 2013-01-09
    • 2010-12-19
    • 1970-01-01
    • 2021-09-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多