database - MongoDB:在没有 MapReduce 的情况下对对象中的值求和

标签 database mongodb aggregation-framework

我有一个对象集合:

{
    "_id" : "01",
    "properties" : {
        "colors" : {
            "red" : 0.8891772,
            "blue" : 0.7580757,
            "green" : 0.4345628,
            "white" : 0.7373822,
            "black" : 0.93228924,
            ...
            "purple" : 0.83328924,
    }
}

颜色有更多上面显示的键。此外,并非每个对象都具有完全相同的键,例如对象可能根本没有 properties.colors.red。

我需要对颜色键的值求和,以便输出看起来像:

/* 1 */
{
    "key" : "Red",
    "value" : 2723.1982
}

/* 2 */
{
    "key" : "Blue",
    "value" : 972172.271
}

...

其中值是该颜色值的总和。

编辑

事实上,比每个属性的总和更好。颜色是原始集合中文档总数的总和的平均值。

例如:

{
    "_id" : "01",
    "properties" : {
        "colors" : {
            "red" : 2.0,
            "blue" : 4.0,
    }
}

{
    "_id" : "02",
    "properties" : {
        "colors" : {
            "red" : 2.0,
            "black" : 8.0,
    }
}

应该导致:

/* 1 */
{
    "key" : "red",
    "value" : 2.0
}

/* 2 */
{
    "key" : "blue",
    "value" : 2.0
}

/* 3 */
{
    "key" : "black",
    "value" : 4.0
}

最佳答案

您必须同时运行两个管道:一个只对所有文档进行计数,另一个按颜色聚合。您可以使用 $facet 来做到这一点.第一个管道相当简单:你只需要 $count获取元素的数量。您可以使用 $objectToArray 开始第二次聚合这会将您的嵌套对象转换为一组键和值(kv 字段)。然后你可以运行 $unwind在该数组上获取每个条目的单个文档以便能够使用 $group$sum。然后你只需要 $project 来 reshape 最终结果。最后你需要 $divide将每个结果除以集合中的元素数。尝试:

db.col.aggregate([
    {
        $facet: {
            total: [ { $count: "value" } ],
            agg: [
                {
                    $project: {
                        colors: {
                            $objectToArray: "$properties.colors"
                        }
                    }
                },
                {
                    $unwind: "$colors"
                },
                {
                    $group: {
                        _id: "$colors.k",
                        v: { $sum: "$colors.v" }
                    }
                }
            ]
        }
    },
    {
        $unwind: "$total"
    },
    {
        $unwind: "$agg"
    },
    {
        $project: {
            _id: 0,
            key: "$agg._id",
            value: { $divide: [ "$agg.v", "$total.value" ] }
        }
    }
])

关于database - MongoDB:在没有 MapReduce 的情况下对对象中的值求和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53461476/

相关文章:

mysql - 用一个元组引用多行

sql - 执行存储在表列中的动态 SQL 语句

database - PostgreSQL : 'psql: error: could not connect to server: No such file or directory' . s.PGSQL.5432

mongodb - 使用 mongodb 的多级 $group

excel - 如何在excel中输入数字并转换为时间

javascript - Mongodb 查找 - 或运算符?

javascript - Mongoose 喜欢 SQL 与最新日期不同

javascript - 使用 $sum 和 $cond 获取值的 $sum,而不是 mongo 中实例的总和

mongodb - 如何避免 mongodb 聚合框架中的 $pushing null

MongoDB 管道聚合将值加在一起