我有一个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" } } )
非常感谢您的回答!
答案 0 :(得分:0)
所以这里的结构确实存在一些问题,你真的“应该”改变它
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()
方法处理它的速度要快得多,并为大型结果集返回一个游标:
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评估,运行速度要慢得多。