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
実際に何が起こっているかを示すために、小さなテスト ケースを作成しました。ユーザー ID の配列である属性を持つusers
コレクションがあるとします。friends
> 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 に設定されていると仮定すると、MongoHQ のメソッドによって返される出力は次のようになります。users
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"
}
}