2017年の更新
$ lookupは、ローカルフィールドとして配列を直接使用できるようになりました。 $unwind
もはや必要ありません。
古い答え
$lookup
集約パイプラインステージは、配列と直接連携しません。設計の主な目的は、可能な関連データの「1対多」タイプの結合(または実際には「ルックアップ」)としての「左結合」です。ただし、値は配列ではなく単一であることが意図されています。
したがって、$lookup
を実行する前に、まずコンテンツを「非正規化」する必要があります。 これが機能するための操作。つまり、$unwind
を使用するということです。 :
db.orders.aggregate([
// Unwind the source
{ "$unwind": "$products" },
// Do the lookup matching
{ "$lookup": {
"from": "products",
"localField": "products",
"foreignField": "_id",
"as": "productObjects"
}},
// Unwind the result arrays ( likely one or none )
{ "$unwind": "$productObjects" },
// Group back to arrays
{ "$group": {
"_id": "$_id",
"products": { "$push": "$products" },
"productObjects": { "$push": "$productObjects" }
}}
])
$lookup
の後 各配列メンバーと一致すると、結果は配列自体になるため、$unwind
もう一度、$group
$push
へ 最終結果のための新しい配列。
見つからない「左結合」の一致は、指定された製品の「productObjects」の空の配列を作成するため、2番目の$unwind
のときに「product」要素のドキュメントを無効にすることに注意してください。 と呼ばれます。
配列に直接適用するのは良いことですが、特異値を可能な数に一致させることにより、これが現在どのように機能するかを示しています。
$lookup
として は基本的に非常に新しく、現在、.populate()
の「貧乏人バージョン」としてマングースに精通している人にはおなじみのように機能します。 そこで提供される方法。違いは、$lookup
クライアントではなく「結合」の「サーバー側」処理を提供し、$lookup
の「成熟度」の一部を提供します。 現在、.populate()
に欠けています オファー(配列で直接ルックアップを補間するなど)。
これは実際にはSERVER-22881の改善に割り当てられた問題であるため、運が良ければ次のリリースまたはその直後のリリースにヒットする可能性があります。
設計原則として、現在の構造は良いものでも悪いものでもありませんが、「結合」を作成するときにオーバーヘッドが発生する可能性があります。そのため、MongoDBの最初の基本原則が適用されます。ここで、1つのコレクションに「事前に参加」されたデータを「使用」できる場合は、そうするのが最善です。
$lookup
について言えるもう1つのこと 一般的な原則として、ここでの「参加」の目的は、ここに示されているのとは逆の方法で作業することです。したがって、他のドキュメントの「関連ID」を「親」ドキュメント内に保持するのではなく、「関連ドキュメント」に「親」への参照が含まれている場合が最も効果的な一般原則です。
したがって、$lookup
マングースの.populate()
のようなものとは逆の「関係設計」で、「最もよく機能する」と言えます。 クライアント側の結合を実行します。代わりに、各「多く」内の「1つ」を識別することにより、$unwind
を必要とせずに、関連するアイテムを取り込むだけです。 最初にアレイ。