node.js - 在带有 MongoDB 聚合的字典数组上使用 $mergeObjects

标签 node.js mongodb mongodb-query aggregation-framework

我正在尝试收集每个用户的任务统计数据的总累积值(按城市分组)。

这是我的输入:

[
    {
        "missions": {
            "Denver": {
                "savedTowers": 3,
                "savedCity": 0,
                "hoursFasted": 68,
                "fastPointsEarned": 4080
            },
            "Boston": {
                "savedTowers": 2,
                "savedCity": 0,
                "hoursFasted": 32,
                "fastPointsEarned": 1920
            }
        }
    },
    {
        "missions": {
            "Denver": {
                "savedTowers": 4,
                "savedCity": 0,
                "hoursFasted": 87,
                "fastPointsEarned": 5220
            },
            "Boston": {
                "savedTowers": 7,
                "savedCity": 1,
                "hoursFasted": 120,
                "fastPointsEarned": 7200
            }
        }
    }
]

这是代码:

db.collection("users").aggregate([
    {
        "$match": {
            "missions": {
                "$exists": true,
                "$gt": {}
            }
        }
    },
    {
        "$project": {
            "_id": 0,
            "city": {
                "$objectToArray": "$missions"
            }
        }
    },
    {
        "$unwind" : "$city"
    },
    {
        "$group": {
            "_id": {
                "city": "$city.k"
            },
            "cities": {
                "$addToSet": "$city.k"
            },
            "stats": {
                "$addToSet": "$city.v"
            },
            "players": {
                "$sum": 1
            }
        }
    },
    {
        "$project": {
            "_id": 0,
            "city": "$_id.city",
            "stats": {
                "$mergeObjects": "$stats"
            },
            "players": "$players"
        }
    }
]).toArray(function(err, response) {
    if (err != null) {
        console.log("Error: " + err.message);
        handleError(res, "Failed to fetch Mission Analytics", err.message);
    } else {
        res.status(200).send({ "mission_stats": response });                
    }
});

这是实际输出:

{
    "mission_stats": [
        {
            "city": "Boston",
            "stats": {
                "savedTowers": 2,
                "savedCity": 0,
                "hoursFasted": 32,
                "fastPointsEarned": 1920
            },
            "players": 2
        },
        {
            "city": "Denver",
            "stats": {
                "savedTowers": 3,
                "savedCity": 0,
                "hoursFasted": 68,
                "fastPointsEarned": 4080
            },
            "players": 2
        }
    ]
}

这是预期的输出:

{
    "mission_stats": [
        {
            "city": "Boston",
            "stats": {
                "savedTowers": 9,
                "savedCity": 0,
                "hoursFasted": 152,
                "fastPointsEarned": 9120
            },
            "players": 2
        },
        {
            "city": "Denver",
            "stats": {
                "savedTowers": 7,
                "savedCity": 0,
                "hoursFasted": 155,
                "fastPointsEarned": 9300
            },
            "players": 2
        }
    ]
}

为什么 $mergeObjects 将统计数据数组缩减为一个对象,但也未能合并这些值?我没有在最终合并对象中看到累积值。

最佳答案

您将使用最后一个 $mergeObjects 操作覆盖统计信息。

您可以尝试以下聚合(未测试)

您必须将值对象转换为键值对数组,然后使用 $unwind+$group 按每个键进行分组并累积统计信息。返回命名键值对象的最后一步。

db.colname.aggregate([
  /** match stage **/
  {"$project":{"city":{"$objectToArray":"$missions"}}},
  {"$unwind":"$city"},
  {"$addFields":{"city-v":{"$objectToArray":"$city.v"}}},
  {"$unwind":"$city-v"},
  {"$group":{
    "_id":{"id":"$city.k","key":"$city-v.k"},
    "stats":{"$sum":"$city-v.v"}
  }},
  {"$group":{
    "_id":"$_id.id",
    "players":{"$sum":1},
    "stats":{"$mergeObjects":{"$arrayToObject":[[["$_id.key","$stats"]]]}}
  }}
])

关于node.js - 在带有 MongoDB 聚合的字典数组上使用 $mergeObjects,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58546649/

相关文章:

mysql - 无法使用 OneToMany 关系添加新记录

javascript - Mongo - 基于名称的值总和的聚合

javascript - 在 Mongoose 模型中保存修改后的文档(带有修改后的子文档数组)

c# - Mongodb C# 驱动程序仅返回数组中匹配的子文档

java - 相当于 MongoCursor 快照的 MongoDB Java 驱动程序

node.js - Node js -如何从数组中删除特定的_id数据

node.js - 如何创建针对 Electron 平台的 cordova 插件?

javascript - 返回异步数据然后在 Node.js 中同步导出

python - PyMongo 按多个键分组

mongodb - Mongodb - 过滤嵌套数组中的数据元素