【问题标题】:Get percentages with MongoDB aggregate $group使用 MongoDB 聚合 $group 获取百分比
【发布时间】:2019-06-24 20:25:59
【问题描述】:

我想从 MongoDB 聚合中的组管道中获取百分比。

我的数据:

{
    _id : 1,
    name : 'hello',
    type : 'big'
},
{
    _id : 2,
    name : 'bonjour',
    type : 'big'
},
{
    _id : 3,
    name : 'hi',
    type : 'short'
},
{
    _id : 4,
    name : 'salut',
    type : 'short'
},
{
    _id : 5,
    name : 'ola',
    type : 'short'
}

我的请求按类型和计数分组:

[{
    $group : {
        _id : {
            type : '$type'
        },
        "count" : {
            "$sum" : 1
        }
    }
}]

结果:

[
    {
        _id {
            type : 'big',
        },
        count : 2
    },
    {
        _id {
            type : 'short',
        },
        count : 3
    }
]

但我想要计数和百分比,就像这样:

[
    {
        _id {
            type : 'big',
        },
        count: 2,
        percentage: 40%
    },
    {
        _id {
            type : 'short',
        },
        count: 3,
        percentage: 60%
    }
]

但我不知道该怎么做。我试过$divide 和其他东西,但没有成功。你能帮帮我吗?

【问题讨论】:

    标签: mongodb aggregation-framework


    【解决方案1】:

    如果值包含%,我认为percentage 应该是字符串

    首先获取你需要count的文档号。

    var nums = db.collection.count();
    
    db.collection.aggregate(
        [
            { "$group": { "_id": {"type":  "$type"}, "count": { "$sum": 1 }}},    
            { "$project": { 
                "count": 1, 
                "percentage": { 
                    "$concat": [ { "$substr": [ { "$multiply": [ { "$divide": [ "$count", {"$literal": nums }] }, 100 ] }, 0,2 ] }, "", "%" ]}
                }
            }
        ]
    )
    

    结果

    { "_id" : { "type" : "short" }, "count" : 3, "percentage" : "60%" }
    { "_id" : { "type" : "big" }, "count" : 2, "percentage" : "40%" }
    

    【讨论】:

    • 如何将百分比值四舍五入到小数点后两位?在您的解决方案中,如果“百分比”值为 16.66,它将仅返回“16%”,我应该在您的解决方案中进行哪些编辑以使其返回“16.70%”?
    • @TonyMathew 对百分比进行四舍五入查看 $round 4.2 中的新功能或查看此answer
    • 你能不能也上这个? stackoverflow.com/questions/61145727/…
    【解决方案2】:

    首先使用 count 方法找到集合中的文档总数,然后使用该计数变量在聚合中计算 percentage,如下所示:

    var totalDocument = db.collectionName.count() //count total doc.
    

    在聚合中使用totalDocument,如下所示:

    db.collectionName.aggregate({"$group":{"_id":{"type":"$type"},"count":{"$sum":1}}},
                                {"$project":{"count":1,"percentage":{"$multiply":[{"$divide":[100,totalDocument]},"$count"]}}})
    

    编辑

    如果您需要在单个 aggregation 查询中执行此操作,则 unwind 用于聚合,但使用 unwind 它会创建 Cartesian problem,请检查以下聚合查询:

    db.collectionName.aggregate({"$group":{"_id":null,"count":{"$sum":1},"data":{"$push":"$$ROOT"}}},
                                {"$unwind":"$data"},
                                 {"$group":{"_id":{"type":"$data.type"},"count":{"$sum":1},
                                           "total":{"$first":"$count"}}},
                                 {"$project":{"count":1,"percentage":{"$multiply":[{"$divide":[100,"$total"]},"$count"]}}}
                                ).pretty()
    

    我建议首先找出总计数,并根据第一个查询在聚合中使用该计数。

    【讨论】:

    • 谢谢。事实上,听起来不可能只用一个聚合得到结果。
    • 是的,在一次聚合检查中是可能的 EDIT 但在一次聚合中出现问题 unwind 数据并创建多个文档。
    猜你喜欢
    • 2023-03-07
    • 2017-01-19
    • 2022-10-05
    • 1970-01-01
    • 2020-03-19
    • 2021-06-11
    • 2019-01-31
    • 2022-01-12
    相关资源
    最近更新 更多