MapReduceは別のスレッドでJavaScriptを実行し、提供されたコードを使用してドキュメントの一部を出力および削減し、特定のフィールドに集約します。あなたは確かに各「fieldValue」を集約するものとして演習を見ることができます。アグリゲーションフレームワークもこれを実行できますが、アグリゲーションは個別のJavaScriptスレッドではなく、C ++のサーバーで実行されるため、はるかに高速になります。ただし、集約フレームワークは16MBより多くのデータを返す可能性があります。その場合、データセットのより複雑なパーティション分割を行う必要があります。
しかし、問題はこれよりもはるかに単純なようです。プロファイルごとに、他のプロファイルが特定の属性を共有しているものを見つけたいだけです。データセットのサイズやパフォーマンス要件を知らなくても、fieldValuesにインデックスがあると想定しているので、クエリを実行すると効率的です。その上で、この単純なループで必要な結果を得ることができます:
> db.profiles.find().forEach( function(p) {
print("Matching profiles for "+tojson(p));
printjson(
db.profiles.find(
{"fieldValues": {"$in" : p.fieldValues},
"_id" : {$gt:p._id}}
).toArray()
);
} );
出力:
Matching profiles for {
"_id" : 1,
"firstName" : "John",
"lastName" : "Smith",
"fieldValues" : [
"favouriteColour|red",
"food|pizza",
"food|chinese"
]
}
[
{
"_id" : 2,
"firstName" : "Sarah",
"lastName" : "Jane",
"fieldValues" : [
"favouriteColour|blue",
"food|pizza",
"food|mexican",
"pets|yes"
]
},
{
"_id" : 3,
"firstName" : "Rachel",
"lastName" : "Jones",
"fieldValues" : [
"food|pizza"
]
}
]
Matching profiles for {
"_id" : 2,
"firstName" : "Sarah",
"lastName" : "Jane",
"fieldValues" : [
"favouriteColour|blue",
"food|pizza",
"food|mexican",
"pets|yes"
]
}
[
{
"_id" : 3,
"firstName" : "Rachel",
"lastName" : "Jones",
"fieldValues" : [
"food|pizza"
]
}
]
Matching profiles for {
"_id" : 3,
"firstName" : "Rachel",
"lastName" : "Jones",
"fieldValues" : [
"food|pizza"
]
}
[ ]
明らかに、クエリを微調整して、すでに一致したプロファイルを除外しないようにすることができます({$gt:p._id}
を変更することにより) {$ne:{p._id}}
へ およびその他の調整。しかし、集約フレームワークまたはmapreduceを使用することでどのような付加価値が得られるかはわかりません。これは、フィールドの1つで単一のコレクションを実際に集約していないためです(表示する出力の形式から判断します)。出力形式の要件が柔軟な場合は、組み込みの集計オプションの1つを使用することもできます。
個々のfieldValuesを集計すると、これがどのようになるかを確認しましたが、悪くはありません。出力がこれと一致する場合に役立つ可能性があります。
> db.profiles.aggregate({$unwind:"$fieldValues"},
{$group:{_id:"$fieldValues",
matchedProfiles : {$push:
{ id:"$_id",
name:{$concat:["$firstName"," ", "$lastName"]}}},
num:{$sum:1}
}},
{$match:{num:{$gt:1}}});
{
"result" : [
{
"_id" : "food|pizza",
"matchedProfiles" : [
{
"id" : 1,
"name" : "John Smith"
},
{
"id" : 2,
"name" : "Sarah Jane"
},
{
"id" : 3,
"name" : "Rachel Jones"
}
],
"num" : 3
}
],
"ok" : 1
}
これは基本的に、「fieldValueごとのfieldValue($ unwind)グループごとに、一致するプロファイル_idと名前の配列で、各fieldValueが累積する一致の数($ group)をカウントし、それに一致するプロファイルが1つしかないものを除外します。
>