首页 > 解决方案 > mongodb map减少值未定义

问题描述

我在 mongodb 中有以下集合-

> db.games.find().pretty();
{
    "_id" : ObjectId("5db06c02e08772b58596ec72"),
    "name" : "Cricket",
    "genre" : "sport",
    "rating" : 10
}
{
    "_id" : ObjectId("5db06c02e08772b58596ec73"),
    "name" : "Football",
    "genre" : "sport",
    "rating" : 100,
    "achievement" : "champion",
    "games" : [
        {
            "score" : 20
        },
        {
            "score" : 30
        },
        {
            "score" : 22
        },
        {
            "score" : 145
        }
    ]
}
{
    "_id" : ObjectId("5db06c02e08772b58596ec74"),
    "name" : "Ludo",
    "genre" : "indoor",
    "rating" : 1
}
{
    "_id" : ObjectId("5db06c02e08772b58596ec75"),
    "name" : "Badminton",
    "genre" : "indoor",
    "rating" : 60,
    "games" : [
        {
            "score" : 34
        },
        {
            "score" : 12
        },
        {
            "score" : 50
        }
    ]
}
{
    "_id" : ObjectId("5db06c02e08772b58596ec76"),
    "name" : "Swimming",
    "genre" : "water",
    "rating" : 50
}
{
    "_id" : ObjectId("5db06c02e08772b58596ec77"),
    "name" : "Running",
    "genre" : "atheletics",
    "rating" : 70
}
{
    "_id" : ObjectId("5db06c02e08772b58596ec78"),
    "name" : "Shotput",
    "genre" : "atheletics",
    "rating" : 66
}

我想对集合中每个游戏的分数求和。为此,我尝试按如下方式实现 map reduce -

> db.games.mapReduce( function(){emit(this.name,this.score)}, function(key,values) {return Array.sum(values)}, {out:"out_scores"});
{
    "result" : "out_scores",
    "timeMillis" : 330,
    "counts" : {
        "input" : 7,
        "emit" : 7,
        "reduce" : 0,
        "output" : 7
    },
    "ok" : 1
}

但是结果集合中的值未定义如下 -

db.out_scores.find().pretty();
{ "_id" : "Badminton", "value" : undefined }
{ "_id" : "Cricket", "value" : undefined }
{ "_id" : "Football", "value" : undefined }
{ "_id" : "Ludo", "value" : undefined }
{ "_id" : "Running", "value" : undefined }
{ "_id" : "Shotput", "value" : undefined }
{ "_id" : "Swimming", "value" : undefined }

我期待每场比赛的得分总和。我在这里做错了什么?

标签: jsonmongodbnosql

解决方案


也许这个查询可能会有所帮助?

db.games.aggregate(
[
    { $unwind: { path: "$games", preserveNullAndEmptyArrays: true }},
    { $group: {
        _id: "$name",
        score: { $sum:  "$games.score" }
    }}
])

结果:

{ "_id" : "Shotput", "score" : 0 }
{ "_id" : "Running", "score" : 0 }
{ "_id" : "Ludo", "score" : 0 }
{ "_id" : "Swimming", "score" : 0 }
{ "_id" : "Badminton", "score" : 96 }
{ "_id" : "Football", "score" : 217 }
{ "_id" : "Cricket", "score" : 0 }

** 如果还想用 mapreduce...**

根本问题是嵌套数据。需要参考games.score角度的数据。map reduce 的映射功能需要这个逻辑。

db.games.mapReduce( function(){
  var sum_of_score = 0;

  if (this.games != undefined) {
    for (var i=0; i<this.games.length; i++) {
      sum_of_score += this.games[i].score;
    }
  }
  emit(this.name, sum_of_score)
}, function(key, values) { }, {out:"out_scores"});

询问:

db.out_scores.find()

结果:

{ "_id" : "Badminton", "value" : 96 }
{ "_id" : "Cricket", "value" : 0 }
{ "_id" : "Football", "value" : 217 }
{ "_id" : "Ludo", "value" : 0 }
{ "_id" : "Running", "value" : 0 }
{ "_id" : "Shotput", "value" : 0 }
{ "_id" : "Swimming", "value" : 0 }

推荐阅读