2

Map/Reduceから移行するために新しいAFを試しています。私はこのような何百万ものオブジェクトを持っています:

{
 _id: ObjectID,
 owner: 1,
 tags: [
   {text: "dog", score: 5}, 
   {text: "cat", score: 3}, 
   {text: "hamster", score:1}]
}

{
 _id: ObjectID,
 owner: 2,
 tags: [
   {text: "cat", score: 8}, 
   {text: "fish", score: 4}]
}

そして、所有者がXである「猫」と「魚」のすべての一致のカウントを使用してレポートを作成したいと思います。

これまでのところ、入力タグ["cat"、"fish"]が次のようになっていると仮定してパイプラインを作成しています。

{
  $match: { owner: X, $in: {"tags.text": ["cat", "fish"]}}
}, {
  $project: {text: "$tags.text"},
}, {
  $unwind: "$text",
}, {
  $match: {"text": {$in: {"tags": ["cat", "fish"]}}
}, {
  $group: {"_id": "$text", "total: {"$sum": 1}}
}

最初の$matchは、所有者と「tags.txt」にインデックスがあるため、これらの100万個のオブジェクトすべてのサブセットに絞り込むことです。

このパイプラインは少数のタグに対しては正常に機能しますが、100〜1000個の「タグ」を渡して迅速な結果を得ることができる必要があります。次の一致ステップで90%の方法でフィルタリングするだけで、すべてのタグを投影して巻き戻すのは非効率的であるに違いないようです。

より効率的な方法はありますか?たぶんパイプラインのステップを並べ替えますか?

4

1 に答える 1

4

これは、いくつかのタイプミスを除いて私には良さそうです$in。各$matchパイプライン操作での演算子の使用法は、おそらく次のようになります。

{
  $match: {owner: X, "tags.text": {$in: ["cat", "fish"]}}
}, {
  $project: {text: "$tags.text"}
}, {
  $unwind: "$text"
}, {
  $match: {"text": {$in: ["cat", "fish"]}}
}, {
  $group: {"_id": "$text", "total": {"$sum": 1}}
}

$match基本的に、パイプラインのできるだけ早い段階で使用して、パイプラインの後半で処理されるドキュメントの数を制限する必要があります。一致ownerと特定のタグがこれを実現します。$matchまた、に相当する.find()が適切なインデックスを使用して いることを確認する必要があります。

于 2012-09-20T15:08:27.347 に答える