按文档中的键汇总总数

Aggregate totals by Keys in a document

我有一个 mapreduce 函数,我想在 mongoDB 中编写这个函数来计算一个角色被玩了多少次。我的 json 中的相关部分如下所示:

"playerInfo": {
"Player 1": {
  "info":{
          "characterId":17
         }
       },
"Player 2": {
      "info":{
              "characterId":20
             }
       }
}

我想统计每个 "characterId" 在我的文档中存在多少次,有 10 个玩家,从玩家 1 到玩家 10。

两个问题:
1。当我有一个数字作为我的密钥的一部分时,如何在 mongo 中使用 mapreduce。
2。如何在 mapreduce 中连接字符串,以便下方显示的代码正确?

db.LoL.mapReduce( function() 
                    {
                        for (var i in this.playerInfo)
                        {
                            emit(this.playerInfo.'Player '+(i).info.characterId, 1);
                        }

                    },
                  function(keys, values) {
                    return Array.sum(values)
                  }, {out: { merge: "map_reduce_example5" } } )

非常感谢您的回答!

所以这里的结构确实有一些问题,你真的 "should" 改变了它

mapReduce 非常简单,因为您可以通过 Object.keys()

迭代键名
db.LoL.mapReduce(
  function() {
    Object.keys(this.playerInfo).forEach(function(key) {
      emit({ "player": key, "characterId": this.playerInfo[key].info.characterId },  1)
    })
  },
  function(values) { return Array.sum(values) },
  { 
    "query": { "playerInfo": { "$exists": true } }
    "out": { "inline": 1 }
  }
)

如果您将数据格式更改为使用数组,并使用值而不是命名键来属性:

{
  "playerInfo": [
    { "player": "Player 1", "characterId": 17 },
    { "player": "Player 2", "characterId": 20 }
  ]
}

然后 .aggregate() 方法处理这个要快得多,returns 一个用于大型结果集的游标:

db.collection.aggregate([
  { "$unwind": "$playerInfo" },
  { "$group": {
    "_id": "$playerInfo",
    "count": { "$sum": 1 }
  }}
])

使用 MongoDB 3.4 及更高版本,您甚至可以在现有结构上使用

db.LoL.aggregate([
  { "$project": {
    "playerInfo": { "$objectToArray": "$playerInfo" }
  }},
  { "$unwind": "$playerInfo" },
  { "$group": {
     "_id": {
       "player": "$playerInfo.k", 
       "characterId": "$playerInfo.v.info.characterId"
     },
     "count": { "$sum": 1 }
  }}
])

这与 mapReduce 基本相同,只是由于使用了本机运算符而不是运行速度慢得多的 JavaScript 评估,所以速度要快得多。