【问题标题】:Weird MongoDB MapReduce ObjectId.toString() behavior?奇怪的 MongoDB MapReduce ObjectId.toString() 行为?
【发布时间】:2012-08-09 09:46:49
【问题描述】:

我在 MongoHQ 上运行的 mongodb 和在我自己的开发机器上运行的版本之间遇到了一些奇怪的差异。具体来说,当在 MapReduce 映射函数内的对象 id 上调用 .toString() 时,结果会有所不同:

在我自己的机器上:

ObjectId('foo').toString()  // => 'foo'

在 MongoHQ:

ObjectId('foo').toString()  // => 'ObjectId(\'foo\')'

注意:我使用的 id 是实际的 mongodb id - 而不仅仅是这些示例中的 'foo' 等

我希望.toString() 在我自己的机器上表现得像 - 而不是它在 MongoHQ 上的表现。怎么不是?

我的本​​地 OSX 版本的 MongoDB 是使用 Homebrew 安装的,版本为 2.0.1-x86_64

为了展示实际发生的情况,我构建了一个小测试用例。假设我们有一个带有friends 属性的users 集合,它是一个用户ID 数组:

> db.users.find()
{ _id: ObjectId('a'), friends: [ObjectId('b'), ObjectId('c')] },
{ _id: ObjectId('b'), friends: [] },
{ _id: ObjectId('c'), friends: [] }

如您所见,abc 的朋友,而 bc 不是任何人的朋友。

现在让我们看看一个有效的测试算法:

var map = function() {
  this.friends.forEach(function(f) {
    emit(f, { friends: 1, user: user, friend: f.toString() });
  });
};

var reduce = function(k, vals) {
  var result = { friends: 0, user: [], friend: [] };

  vals.forEach(function(val) {
    result.friends += val.friends;
    result.user.push(val.user);
    result.friend.push(val.friend);
  });

  return result;
};

var id = ObjectId('50237c6d5849260996000002');

var query = {
  query   : { friends: id },
  out     : { inline: 1 },
  scope   : { user: id.toString() },
  jsMode  : true,
  verbose : true
};

db.users.mapReduce(map, reduce, query);

假设id 设置为users 集合中某人的朋友的用户ID,那么MongoHQ 上mapReduce 方法返回的输出将如下所示:

{
  "results" : [
    {
      "_id" : ObjectId("50237c555849260996000001"),
      "value" : {
        "friends" : 1,
        "user" : "50237c6d5849260996000002",
        "friend" : "ObjectId(\"50237c555849260996000001\")"
      }
    },
    {
      "_id" : ObjectId("50237c74c271be07f6000002"),
      "value" : {
        "friends" : 1,
        "user" : "50237c6d5849260996000002",
        "friend" : "ObjectId(\"50237c74c271be07f6000002\")"
      }
    }
  ],
  "timeMillis" : 0,
  "timing" : {
    "mapTime" : 0,
    "emitLoop" : 0,
    "reduceTime" : 0,
    "mode" : "mixed",
    "total" : 0
  },
  "counts" : {
    "input" : 1,
    "emit" : 2,
    "reduce" : 0,
    "output" : 2
  },
  "ok" : 1,
}

如你所见,每个结果中的friend属性不仅仅是一个包含id的字符串,而是一个包含实际方法调用的字符串。

如果我在自己的机器上运行,结果数组应该是:

{
  "_id" : ObjectId("50237c555849260996000001"),
  "value" : {
    "friends" : 1,
    "user" : "50237c6d5849260996000002",
    "friend" : "50237c555849260996000001"
  }
},
{
  "_id" : ObjectId("50237c74c271be07f6000002"),
  "value" : {
    "friends" : 1,
    "user" : "50237c6d5849260996000002",
    "friend" : "50237c74c271be07f6000002"
  }
}

【问题讨论】:

    标签: mongodb mapreduce mongohq


    【解决方案1】:

    MongoHQ 运行的 MongoDB 版本与您不同。

    要获得您的自制版本的行为,请尝试更改您的地图功能:

    var map = function() {
      this.friends.forEach(function(f) {
        emit(f, { friends: 1, user: user.str, friend: f.str });
      });
    };
    

    【讨论】:

      猜你喜欢
      • 2014-07-18
      • 2018-07-15
      • 2014-07-17
      • 2015-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-15
      • 1970-01-01
      相关资源
      最近更新 更多