我在 MongoHQ 上运行的 mongodb 和在我自己的开发机器上运行的版本之间遇到了一些奇怪的差异。具体来说,当.toString()
在 MapReduce 映射函数中调用对象 id 时,结果会有所不同:
在我自己的机器上:
ObjectId('foo').toString() // => 'foo'
在 MongoHQ 上:
ObjectId('foo').toString() // => 'ObjectId(\'foo\')'
注意:我使用的 id 是实际的 mongodb id - 而不仅仅是 'foo' 等,如这些示例中
我希望.toString()
表现得像在我自己的机器上 - 而不是它在 MongoHQ 上的表现。怎么不是?
我的本地 OSX 版本的 MongoDB 是使用 Homebrew 安装的,并且是版本2.0.1-x86_64
为了展示实际发生的情况,我构建了一个小测试用例。假设我们有一个users
带有friends
属性的集合,它是一个用户 ID 数组:
> db.users.find()
{ _id: ObjectId('a'), friends: [ObjectId('b'), ObjectId('c')] },
{ _id: ObjectId('b'), friends: [] },
{ _id: ObjectId('c'), friends: [] }
如您所见,与任何人a
是朋友b
,c
在哪里是朋友b
,c
不是朋友。
现在让我们看一个有效的测试算法:
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
中某人的朋友的用户的 id users
,那么 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"
}
}