首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >直方图直方图的结果

直方图直方图的结果
EN

Stack Overflow用户
提问于 2019-07-11 10:16:04
回答 2查看 84关注 0票数 1

我已经通过以下命令生成了一个直方图:

代码语言:javascript
复制
db.mydb.aggregate([{ $bucketAuto: { groupBy: "$userId", buckets: 1e9 } }])

假设我的独立用户少于10亿(并且有足够的内存),这就给出了每个用户的文档数。

代码语言:javascript
复制
User   Docs
=====  ====
userA  3
userB  1
userC  5
userD  1

我想要获得这个直方图的结果,并通过轴心来计算每个文档计数的用户数。

结果将如下所示:

代码语言:javascript
复制
Docs  Users
====  =====
1     2
2     0
3     1
4     0
5     1

在MongoDB中有没有一种简单、实用的方法来实现这一点呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-07-11 13:17:37

你可以从简单的$group stage开始:

代码语言:javascript
复制
db.col.aggregate([
    {
        $group: {
            _id: "$docs",
            count: { $sum: 1 }
        }
    },
    {
        $project: {
            _id: 0,
            docs: "$_id",
            users: "$count"            
        }
    },
    {
        $sort: { docs: 1 }
    }
])

这将为您提供以下结果:

代码语言:javascript
复制
{ "docs" : 1, "users" : 2 }
{ "docs" : 3, "users" : 1 }
{ "docs" : 5, "users" : 1 }

那么没有用户的文档就是缺失的部分。您可以从应用程序或从MongoDB添加它们(如下所示):

代码语言:javascript
复制
db.col.aggregate([
    {
        $group: {
            _id: "$docs",
            count: { $sum: 1 }
        }
    },
    {
        $group: {
            _id: null,
            histogram: { $push: "$$ROOT" }
        }
    },
    {
        $project: {
            values: {
                $map: { 
                    input: { $range: [ { $min: "$histogram._id" }, { $add: [ { $max: "$histogram._id" }, 1 ] } ] },
                    in: {
                        docs: "$$this",
                        users: {
                            $let: {
                                vars: {
                                    current: { $arrayElemAt: [ { $filter: { input: "$histogram", as: "h", cond: { $eq: [ "$$h._id", "$$this" ] } } }, 0 ] }
                                },
                                in: {
                                    $ifNull: [ "$$current.count", 0 ]
                                }
                            }
                        }
                    } 
                }
            }
        }
    },
    {
        $unwind: "$values"
    },
    {
        $replaceRoot: {
            newRoot: "$values"
        }
    }
])

这里的想法是,我们可以通过null生成包含前一阶段的所有文档的单个文档。知道了$min$max的值,我们就可以生成一个$range of numbers和$map,它的范围既可以是现有的计数,也可以是默认值0。然后,我们可以使用$unwind$replaceRange来获得每个文档的单个直方图点。输出:

代码语言:javascript
复制
{ "docs" : 1, "users" : 2 }
{ "docs" : 2, "users" : 0 }
{ "docs" : 3, "users" : 1 }
{ "docs" : 4, "users" : 0 }
{ "docs" : 5, "users" : 1 }
票数 1
EN

Stack Overflow用户

发布于 2019-12-04 11:05:50

mickl's answer绝对让我朝着正确的方向前进。特别是,在这个用例中,使用$group是对$bucketAuto的一个很好的改进。对直方图进行分层的诀窍是在同一个aggregate中多次使用$group阶段。我想这在事后看来是显而易见的。

完整的解决方案在这里:

代码语言:javascript
复制
const h2 = db.mydb.aggregate([
    { $group: { _id: "$userId", count: { $sum: 1 } } },
    { $group: { _id: "$count", count: { $sum: 1 } } },
    { $project: { docs: "$_id", users: "$count" } },
    { $sort: { docs: +1 } }
])
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56980789

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档