Make the MongoDB docs better! We value your opinion. Share your feedback for a chance to win $100.
Click here >
Docs Menu
Docs Home
/ /

$lookup(集計ステージ)

$lookup

バージョン 5.1 での変更。

同じデータベースのコレクションへの左外部結合を実行して、外部コレクションのドキュメントをフィルタリングして処理します。$lookupステージでは、各入力ドキュメントに新しい配列フィールドが追加されます。新しい配列フィールドには、外部コレクションからの一致するドキュメントが含まれます。$lookupステージは、これらの再形成されたドキュメントを次のステージに渡します。

MongoDB 5.1以降では、シャーディングされたコレクションで$lookupを使用できます。

2 つの異なるコレクションの要素を結合するには、 $unionWithパイプライン ステージを使用します。

重要

$lookup を過度に使用すると、クエリ パフォーマンスが低下する可能性があります。$lookup への依存関係を軽減するには、埋め込みデータモデルを使用して関連データを単一のコレクションに保存することを検討してください。

$lookup パフォーマンスの詳細については、パフォーマンスに関する考慮事項 を参照してください。

次の環境でホストされる配置には $lookup を使用できます。

  • MongoDB Atlas はクラウドでの MongoDB 配置のためのフルマネージド サービスです

  • MongoDB Enterprise: サブスクリプションベースの自己管理型 MongoDB バージョン

  • MongoDB Community: ソースが利用可能で、無料で使用できる自己管理型の MongoDB のバージョン

$lookupステージ構文:

{
$lookup:
{
from: <collection to join>,
localField: <field from the input documents>,
foreignField: <field from the documents of the "from" collection>,
let: { <var_1>: <expression>, …, <var_n>: <expression> },
pipeline: [ <pipeline to run> ],
as: <output array field>
}
}

$lookupは、次のフィールドを含むドキュメントを受け入れます。

フィールド
必要性
説明

必須

ローカルコレクションに結合する同じデータベース内の外部コレクションを指定します。

場合によっては、$documents を第 1 ステージとして、frompipeline に置き換えることができます。例については、「 $lookup ステージで $documents ステージを使用する 」を参照してください。

MongoDB 5.1 以降では、 fromコレクションをシャーディングできます。

pipelineが指定されている場合は任意

$lookupステージに入力されるドキュメントからフィールドを指定します。$lookuplocalFieldforeignFieldfrom コレクションのドキュメントから と の等価一致を実行します。入力ドキュメントにlocalField が含まれていない場合、 は一致させる目的でそのフィールドが$lookup nullの値を持つものとして扱います。

pipelineが指定されている場合は任意

外部ドキュメントの foreignField を指定して、ローカルドキュメントの localField と等価一致を実行します。

外部ドキュメントにforeignField 値が含まれていない場合、$lookup は一致にnull 値を使用します。

任意

パイプラインステージで使用する変数を指定します。変数式を使用して、pipelineに入力されたローカルコレクションのドキュメントのフィールドにアクセスします。

パイプラインステージで変数を参照には、"$$<variable>" 構文を使用します。

let $lookup変数には、 にネストされた追加のpipeline ステージを含むパイプラインのステージからアクセス可能です。

  • $matchステージでは、変数にアクセスするために$expr演算子を使用する必要があります。$expr演算子を使用すると、$match構文内で集計式を使用できます。

    $eq演算子に配置されている$lt $lte$gt$gte、 、$expr 、 、 比較演算子は、from $lookupステージで参照される コレクションのインデックスを使用できます。制限:

    • インデックスはフィールドと定数の比較にのみ使用できるため、let オペランドは定数に変換する必要があります。

      たとえば、$a と定数値の比較にはインデックスを使用できますが、$a$b の比較には使用できません。

    • let オペランドが空の値または欠損値に変換される場合の比較には、インデックスは使用されません。

    • マルチキー部分、またはスパースインデックスは使用されません。

  • パイプラインの他の($match 以外の)ステージでは、変数にアクセスするために $expr演算子は必要ありません。

localFieldforeignField が指定されている場合は任意です。

外部コレクションで実行するpipelineを指定します。pipelineは外部コレクションからドキュメントを返します。すべてのドキュメントを返すには、空のpipeline: []を指定します。

にはpipeline $out$mergeステージまたは ステージを含めることはできません。v6.0 以降では、pipeline にはパイプライン内の最初のステージとして$search Atlas Search ステージを含めることができます。詳しくは、「 Atlas Search サポート 」を参照してください。

pipelineは入力ドキュメントのフィールドにアクセスできません。代わりに、letオプションを使用してドキュメントフィールドの変数を定義し、その変数をpipelineステージで参照します。

パイプラインステージで変数を参照には、"$$<variable>" 構文を使用します。

let $lookup変数には、 にネストされた追加のpipeline ステージを含むパイプラインのステージからアクセス可能です。

  • $matchステージでは、変数にアクセスするために$expr演算子を使用する必要があります。$expr演算子を使用すると、$match構文内で集計式を使用できます。

    $eq演算子に配置されている$lt $lte$gt$gte、 、$expr 、 、 比較演算子は、from $lookupステージで参照される コレクションのインデックスを使用できます。制限:

    • インデックスはフィールドと定数の比較にのみ使用できるため、let オペランドは定数に変換する必要があります。

      たとえば、$a と定数値の比較にはインデックスを使用できますが、$a$b の比較には使用できません。

    • let オペランドが空の値または欠損値に変換される場合の比較には、インデックスは使用されません。

    • マルチキー部分、またはスパースインデックスは使用されません。

  • パイプラインの他の($match 以外の)ステージでは、変数にアクセスするために $expr演算子は必要ありません。

必須

入力ドキュメントに追加する新しい配列フィールドの名前を指定します。新しい配列フィールドには、fromコレクションと一致するドキュメントが含まれます。指定した名前がすでに入力ドキュメントに存在する場合、既存のフィールドは上書きされます。

入力ドキュメントのフィールドと外部コレクションのドキュメントのフィールドとの間で等価一致を実行するには、$lookupステージで次の構文を使用します。

{
$lookup:
{
from: <collection to join>,
localField: <field from the input documents>,
foreignField: <field from the documents of the "from" collection>,
pipeline: [ <pipeline to run> ],
as: <output array field>
}
}

注意

この例では 、pipeline は任意であり、ローカルと外部の等価ステージの後に実行されます。

この操作は、次の疑似 SQL ステートメントに対応します。

SELECT *, (
SELECT ARRAY_AGG(*)
FROM <collection to join>
WHERE <foreignField> = <collection.localField>
) AS <output array field>
FROM collection;

注意

このページの SQL ステートメントは、MongoDB 集計パイプライン構文の比較に含まれています。SQL ステートメントは実行できません。

MongoDB の例については、次のページを参照してください。

MongoDB は以下をサポートします。

  • 外部コレクションでパイプラインを実行する。

  • 複数の結合条件。

  • 相関サブクエリと非相関サブクエリ。

MongoDBでは、非相関サブクエリとは、すべての入力ドキュメントが同じ結果を返すことを意味します。相関サブクエリは、ローカル コレクションまたは $lookupinputコレクションのフィールドを使用して、各受信ドキュメントに相関した結果を返す ステージの パイプライン です。

注意

MongoDB5.0 以降では、$lookup $sampleステージ、$sampleRate 演算子、または$rand 演算子を含む、 パイプライン ステージ内の相関のないサブクエリの場合、繰り返される場合はサブクエリが常に再度実行されます。以前は、サブクエリの出力サイズに応じて、サブクエリの出力がキャッシュされるか、サブクエリが再度実行されていました。

MongoDB 相関サブクエリは、内部クエリが外部クエリ値を参照する SQL 相関サブクエリに相当します。SQL 非相関サブクエリは、外部クエリ値を参照しません。

MongoDB 5.0 は簡潔な相関サブクエリもサポートしています。

2 つのコレクションに対して相関サブクエリと非相関サブクエリを実行し、単一の等価一致以外の結合条件を実行するには、次の$lookup構文を使用します。

{
$lookup:
{
from: <foreign collection>,
let: { <var_1>: <expression>, …, <var_n>: <expression> },
pipeline: [ <pipeline to run on foreign collection> ],
as: <output array field>
}
}

この操作は、次の疑似 SQL ステートメントに対応します。

SELECT *, <output array field>
FROM collection
WHERE <output array field> IN (
SELECT <documents as determined from the pipeline>
FROM <collection to join>
WHERE <pipeline>
);

次の例を参照してください。

バージョン 5.0 で追加

MongoDB 5.0 以降、簡潔な相関サブクエリの構文を使用できるようになりました。相関サブクエリは、外部コレクションおよびaggregate()メソッドが実行された「ローカル」コレクションのドキュメントフィールドを参照します。

次の新しい簡潔な構文により、$expr演算子内の外部フィールドとローカルフィールドを等価一致させる必要がなくなります。

{
$lookup:
{
from: <foreign collection>,
localField: <field from local collection's documents>,
foreignField: <field from foreign collection's documents>,
let: { <var_1>: <expression>, …, <var_n>: <expression> },
pipeline: [ <pipeline to run> ],
as: <output array field>
}
}

この操作は、次の疑似 SQL ステートメントに対応します。

SELECT *, <output array field>
FROM localCollection
WHERE <output array field> IN (
SELECT <documents as determined from the pipeline>
FROM <foreignCollection>
WHERE <foreignCollection.foreignField> = <localCollection.localField>
AND <pipeline match condition>
);

以下の例を参照してください。

$lookup$graphLookup のように複数のビューを含む集計を実行する場合、ビューの照合順序は同じである必要があります。

$out または $merge ステージを $lookup ステージに含めることはできません。具体的には、外部コレクションのパイプラインを指定するときに、pipeline フィールドにどちらのステージも含めることはできません。

{
$lookup:
{
from: <collection to join>,
let: { <var_1>: <expression>, …, <var_n>: <expression> },
pipeline: [ <pipeline to execute on the foreign collection> ], // Cannot include $out or $merge
as: <output array field>
}
}

MongoDB 6.0 以降では、 $lookup パイプラインで Atlas Search $search または $searchMeta ステージを指定して、Atlas クラスター上のコレクションを検索できます。$search または $searchMeta ステージは、 $lookup パイプライン内の最初のステージである必要があります。

たとえば、外部コレクションで条件とサブクエリを結合する場合や、簡潔な構文を使用した相関サブクエリを実行する場合は、次に示すようにパイプライン内で$searchまたは$searchMetaを指定できます。

[{
"$lookup": {
"from": <foreign collection>,
localField: <field from the input documents>,
foreignField: <field from the documents of the "from" collection>,
"as": <output array field>,
"pipeline": [{
"$search": {
"<operator>": {
<operator-specification>
}
},
...
}]
}
}]
[{
"$lookup": {
"from": <foreign collection>,
localField: <field from the input documents>,
foreignField: <field from the documents of the "from" collection>,
"as": <output array field>,
"pipeline": [{
"$searchMeta": {
"<collector>": {
<collector-specification>
}
},
...
}]
}
}]

$lookup とともに $search を使った例については、Atlas Search チュートリアルの「$lookup を使用した Atlas Search $search クエリの実行」を参照してください。

MongoDB5.1 以降では、from ステージの パラメーターで$lookup シャーディングされたコレクション を指定できます。

シャーディングされたコレクションをターゲットにしている間は、トランザクション内で $lookup ステージを使用できません

注意

バージョン 7.0.17 以降、スロットベースのクエリ実行エンジンは、7.0 のパッチ バージョンではデフォルトで有効ではなくなりました。スロットベースのクエリ実行エンジンを使用するクエリを使用する場合は、バージョン 8.0 にアップグレードしてください。デフォルトで有効になっている 。

バージョン 6.0 以降、MongoDB は、パイプライン内の先行するすべてのステージもスロット ベースの実行エンジンで実行でき、次の条件のいずれも当てはまらない場合、スロット ベースの実行クエリ エンジンを使用して $lookup ステージを実行できます。

  • $lookup操作は、外部コレクションに対してパイプラインを実行します。この種の操作の例については、「外部コレクションの結合条件とサブクエリ」を参照してください。

  • $lookuplocalField または foreignField は数値コンポーネントを指定します。例: { localField: "restaurant.0.review" }

  • パイプラインに含まれる任意の $lookupfrom フィールドには、ビューまたはシャーディングされたコレクションが明示されます。

詳細については、「$lookup 最適化」を参照してください。

$lookup パフォーマンスは、実行される操作の種類によって異なります。さまざまな$lookup操作のパフォーマンスに関する考慮事項については、次の表を参照してください。

$lookup 操作
パフォーマンスに関する考慮事項
  • $lookup では、外部コレクションに foreignField のインデックスが含まれている場合、単一結合で等価一致を実行する操作のパフォーマンスが向上します。

    重要: foreignField に対応するインデックスが存在しない場合、単一結合で等価一致を実行する $lookup 操作はパフォーマンスが低下する可能性があります。

  • $lookup では、内部パイプラインが外部コレクションのインデックスを参照できる場合、非相関サブクエリを含む操作のパフォーマンスが向上します。

  • ソース コレクションと外部コレクションの間には関係がないため、MongoDB はクエリをキャッシュする前に $lookup サブクエリを一度だけ実行する必要があります。サブクエリはソース コレクション内のどの値にも基づいていません。この動作により、 $lookup 操作の後続の実行時のパフォーマンスが向上します。

  • $lookup では、次の条件が当てはまる場合、相関サブクエリを含む操作は、より優れたパフォーマンスを実現します。

    • 外部コレクションはforeignFieldのインデックスを含みます。

    • 外部コレクションには、内部パイプラインを参照するインデックスが含まれています。

  • パイプラインが多数のドキュメントを $lookup クエリに渡す場合、次の戦略によってパフォーマンスが向上する可能性があります。

    • MongoDB が$lookupクエリに渡すドキュメントの数を減らします。たとえば、$match ステージでより厳しいフィルターを設定します。

    • $lookup サブクエリの内部パイプラインを別のクエリとして実行し、$out を使用して一時コレクションを作成します。 次に、 1 つの結合による等価一致を実行します。

    • データのスキーマを再検討して、ユースケースに最適であることを確認します。

一般的なパフォーマンス戦略については、「インデックス戦略」と「クエリの最適化」を参照してください。

このページの例では、sample_mflixサンプルデータセットのデータを使用します。このデータセットを自己管理型MongoDB配置にロードする方法の詳細については、サンプルデータセットをロードする を参照してください。サンプルデータベースに変更を加えた場合、このページの例を実行するには、データベースを削除して再作成する必要がある場合があります。

次の集計操作では、まず moviesコレクションをruntime1000 より大きい映画をフィルタリングし、次に _id フィールドと movie_id フィールドの commentsコレクションと結合します。

db.movies.aggregate( [
{ $match: { runtime: { $gt: 1000 } } },
{
$lookup: {
from: "comments",
localField: "_id",
foreignField: "movie_id",
as: "movie_comments"
}
},
{
$project: {
_id: 0,
title: 1,
year: 1,
"movie_comments.name": 1,
"movie_comments.text": 1,
"movie_comments.date": 1
}
}
] )
[
{
title: 'Centennial',
year: 1978,
movie_comments: [
{
name: 'Ellaria Sand',
text: 'Excepturi nam nam eum possimus aspernatur autem. Quis nulla optio praesentium ut distinctio explicabo.',
date: ISODate('1995-08-18T03:01:50.000Z')
}
]
},
{ title: 'Baseball', year: 1994, movie_comments: [] }
]

この操作は、次の疑似 SQL ステートメントに対応します。

SELECT *, movie_comments
FROM movies
WHERE movie_comments IN (
SELECT *
FROM comments
WHERE movie_id = movies._id
);

詳細については、「等価一致のパフォーマンスに関する考慮事項」を参照してください。

localFieldが配列の場合、$unwindステージを使用せずに、配列要素をスカラーforeignFieldと照合できます。

次の集計操作では、moviesコレクションと usersコレクションを結合し、moviescast 配列フィールドと users のスカラー nameフィールドを照合します。

db.movies.aggregate( [
{
$match: {
title: {
$in: [ "Roger & Me", "The Sum of Us",
"Centennial" ]
}
}
},
{
$lookup: {
from: "users",
localField: "cast",
foreignField: "name",
as: "cast_users"
}
},
{
$project: {
_id: 0,
title: 1,
year: 1,
cast: 1,
"cast_users.name": 1,
"cast_users.email": 1
}
},
{ $sort: { year: 1 } }
] )
[
{
cast: [
'Raymond Burr',
'Barbara Carrera',
'Richard Chamberlain',
'Robert Conrad'
],
title: 'Centennial',
year: 1978,
cast_users: []
},
{
cast: [
'Michael Moore',
'Roger B. Smith',
'Rhonda Britton',
'Fred Ross'
],
title: 'Roger & Me',
year: 1989,
cast_users: [ { name: 'Michael Moore', email: 'michael_moore@fakegmail.com' } ]
},
{
cast: [
'Jack Thompson',
'Russell Crowe',
'John Polson',
'Deborah Kennedy'
],
title: 'The Sum of Us',
year: 1994,
cast_users: [
{
name: 'Deborah Kennedy',
email: 'deborah_kennedy@fakegmail.com'
}
]
}
]

$mergeObjects 演算子は、複数のドキュメントを 1 つのドキュメントに結合します。

The following 操作 uses$lookup を使用してmovies コレクションとcomments コレクションを結合し、$mergeObjects$replaceRoot を使用して最初のコメントdocumentを映画documentとマージします。

db.movies.aggregate( [
{ $match: { runtime: { $gt: 1000 } } },
{
$lookup: {
from: "comments",
localField: "_id",
foreignField: "movie_id",
as: "movie_comments"
}
},
{
$replaceRoot: {
newRoot: {
$mergeObjects: [
{ $arrayElemAt: [ "$movie_comments", 0 ] },
"$$ROOT"
]
}
}
},
{
$project: {
_id: 0,
title: 1,
year: 1,
genres: 1,
name: 1,
email: 1,
text: 1,
date: 1
}
}
] )
[
{
name: 'Ellaria Sand',
email: 'indira_varma@gameofthron.es',
text: 'Excepturi nam nam eum possimus aspernatur autem. Quis nulla optio praesentium ut distinctio explicabo.',
date: ISODate('1995-08-18T03:01:50.000Z'),
genres: [ 'Action', 'Adventure', 'Drama' ],
title: 'Centennial',
year: 1978
},
{
genres: [ 'Documentary', 'History', 'Sport' ],
title: 'Baseball',
year: 1994
}
]

パイプラインは外部コレクションに対して実行でき、複数の結合条件を含めることができます。$expr 演算子を使用すると、接続詞や不等価一致など、より複雑な結合条件が可能になります。

結合条件は、aggregate()メソッドが実行されたローカル コレクション内のフィールドを参照し、外部コレクション内のフィールドを参照できます。これにより、2つのコレクション間の相関サブクエリが可能になります。

MongoDB 5.0 は簡潔な相関サブクエリをサポートしています。

次の例:

  • _id フィールドと movie_id フィールドを使用して movies コレクションと comments コレクションを結合します。

  • 映画の公開年後に投稿されたコメントのみを含めるようにコメントをフィルタリングします。

db.movies.aggregate( [
{
$match: {
title: {
$in: [ "Class Action", "Kafka", "Corpse Bride" ]
}
}
},
{
$lookup: {
from: "comments",
localField: "_id",
foreignField: "movie_id",
let: { movie_year: "$year" },
pipeline: [
{
$match: {
$expr: {
$gt: [
{ $year: "$date" }, "$$movie_year"
]
}
}
},
{ $project: { _id: 0, name: 1, date: 1 } }
],
as: "post_release_comments"
}
},
{
$project: {
_id: 0,
title: 1,
year: 1,
post_release_comments: 1
}
}
] )
[
{
year: 1991,
title: 'Class Action',
post_release_comments: [
{ name: 'Khal Drogo', date: ISODate('2016-12-06T07:17:03.000Z') }
]
},
{
year: 1991,
title: 'Kafka',
post_release_comments: [
{ name: 'Khal Drogo', date: ISODate('1998-05-10T03:10:20.000Z') }
]
},
{ year: 2005, title: 'Corpse Bride', post_release_comments: [] }
]

この操作は、次の疑似 SQL ステートメントに対応します。

SELECT *, post_release_comments
FROM movies
WHERE post_release_comments IN (
SELECT name, date
FROM comments
WHERE movie_id = movies._id
AND YEAR(date) > movies.year
);

$expr 演算子に配置されている $eq$lt$lte$gt$gte 比較演算子では、$lookup ステージで参照される from コレクションにインデックスを使用できます。制限:

  • インデックスはフィールドと定数の比較にのみ使用できるため、let オペランドは定数に変換する必要があります。

    たとえば、$a と定数値の比較にはインデックスを使用できますが、$a$b の比較には使用できません。

  • let オペランドが空の値または欠損値に変換される場合の比較には、インデックスは使用されません。

  • マルチキー部分、またはスパースインデックスは使用されません。

たとえば、インデックス{ movie_id: 1 } commentsコレクションに存在する場合:

  • comments.movie_idフィールドの等価一致はインデックスを使用します。

Tip

集計パイプラインの $lookup ステージでは、外部コレクションに対してパイプラインを実行できるため、非相関サブクエリが可能になります。非相関サブクエリは、ローカル ドキュメント フィールドを参照しません。

注意

MongoDB5.0 以降では、$lookup $sampleステージ、$sampleRate 演算子、または$rand 演算子を含む、 パイプライン ステージ内の相関のないサブクエリの場合、繰り返される場合はサブクエリが常に再度実行されます。以前は、サブクエリの出力サイズに応じて、サブクエリの出力がキャッシュされるか、サブクエリが再度実行されていました。

次の操作では、moviesコレクションからの さらに 上映時間が 1000 分を超える映画と usersコレクションを結合します。

db.users.aggregate( [
{
$match: {
email: { $in: [
"mark_addy@gameofthron.es",
"lena_headey@gameofthron.es"
] }
}
},
{
$lookup: {
from: "movies",
pipeline: [
{ $match: { runtime: { $gt: 1000 } } },
{ $project: { _id: 0, title: 1, year: 1 } }
],
as: "long_movies"
}
},
{
$project: {
_id: 0, name: 1, email: 1, long_movies: 1
}
}
] )
[
{
name: 'Robert Baratheon',
email: 'mark_addy@gameofthron.es',
long_movies: [
{ title: 'Centennial', year: 1978 },
{ title: 'Baseball', year: 1994 }
]
},
{
name: 'Cersei Lannister',
email: 'lena_headey@gameofthron.es',
long_movies: [
{ title: 'Centennial', year: 1978 },
{ title: 'Baseball', year: 1994 }
]
}
]

この操作は、次の疑似 SQL ステートメントに対応します。

SELECT *, long_movies
FROM users
WHERE long_movies IN (
SELECT title, year
FROM movies
WHERE runtime > 1000
);

詳細については、「非相関サブクエリのパフォーマンスに関する検討事項 」を参照してください。

バージョン 5.0 で追加

MongoDB 5.0以降、集計パイプラインの$lookupステージでは、コレクション間の結合を改善する簡潔な相関サブクエリ構文がサポートされています。 新しい簡潔な構文により、 ステージの$expr $match演算子内の外部フィールドとローカルフィールドを等価一致させる必要がなくなります。

次の例:

  • localField _idforeignField movie_id と一致させることで、movies コレクションと comments コレクションを結合します。一致は pipeline が実行される前に実行されます。

  • それぞれ $$movie_year$date を使用してアクセスされた、映画の公開年後に投稿されたもののみを含むようにコメントをフィルタリングします。

db.movies.aggregate( [
{
$match: {
title: { $in: [
"I Don't Kiss",
"Lucky Luke",
"Mississippi Masala"
] }
}
},
{
$lookup: {
from: "comments",
localField: "_id",
foreignField: "movie_id",
let: { movie_year: "$year" },
pipeline: [
{
$match: {
$expr: {
$gt: [
{ $year: "$date" }, "$$movie_year"
]
}
}
},
{ $project: { _id: 0, name: 1, date: 1 } }
],
as: "post_release_comments"
}
},
{
$project: {
_id: 0,
title: 1,
year: 1,
post_release_comments: 1
}
}
] )
[
{
title: "I Don't Kiss",
year: 1991,
post_release_comments: [
{
name: 'Brandon Hardy',
date: ISODate('2016-09-18T11:11:34.000Z')
}
]
},
{
title: 'Lucky Luke',
year: 1991,
post_release_comments: [
{
name: 'Kelsey Smith',
date: ISODate('2010-01-13T17:55:01.000Z')
}
]
},
{
title: 'Mississippi Masala',
year: 1991,
post_release_comments: [
{
name: 'Phillip Collins',
date: ISODate('2010-05-13T08:04:22.000Z')
}
]
}
]

この例では、MongoDB バージョン 5.0 以前の古い冗語構文を使用しており、以前の簡潔な例と同様の結果を返します。

db.movies.aggregate( [
{
$match: {
title: { $in: [
"I Don't Kiss",
"Lucky Luke",
"Mississippi Masala"
] }
}
},
{
$lookup: {
from: "comments",
let: { movie_id: "$_id", movie_year: "$year" },
pipeline: [
{
$match: {
$expr: {
$and: [
{ $eq: [ "$movie_id", "$$movie_id" ] },
{ $gt: [
{ $year: "$date" }, "$$movie_year"
] }
]
}
}
},
{ $project: { _id: 0, name: 1, date: 1 } }
],
as: "post_release_comments"
}
},
{
$project: {
_id: 0,
title: 1,
year: 1,
post_release_comments: 1
}
}
] )
[
{
title: "I Don't Kiss",
year: 1991,
post_release_comments: [
{
name: 'Brandon Hardy',
date: ISODate('2016-09-18T11:11:34.000Z')
}
]
},
{
title: 'Lucky Luke',
year: 1991,
post_release_comments: [
{
name: 'Kelsey Smith',
date: ISODate('2010-01-13T17:55:01.000Z')
}
]
},
{
title: 'Mississippi Masala',
year: 1991,
post_release_comments: [
{
name: 'Phillip Collins',
date: ISODate('2010-05-13T08:04:22.000Z')
}
]
}
]

前の例は、次の疑似 SQL ステートメントに対応します。

SELECT *, post_release_comments
FROM movies
WHERE post_release_comments IN (
SELECT *
FROM comments
WHERE comments.movie_id = movies._id
AND YEAR(comments.date) > movies.year
);

詳細については、「相関サブクエリのパフォーマンスに関する検討事項」を参照してください。

このページのC#の例では、Atlasサンプルデータセットsample_mflixデータベースを使用します。MongoDB Atlasクラスターを無料で作成して、サンプルデータセットをロードする方法については、 MongoDB .NET/ C#ドライバーのドキュメントの「 開始 」を参照してください。

次の Movie クラスは、sample_mflix.movies コレクション内のドキュメントをモデル化します。

public class Movie
{
public ObjectId Id { get; set; }
public int Runtime { get; set; }
public string Title { get; set; }
public string Rated { get; set; }
public List<string> Genres { get; set; }
public string Plot { get; set; }
public ImdbData Imdb { get; set; }
public int Year { get; set; }
public int Index { get; set; }
public string[] Comments { get; set; }
[BsonElement("lastupdated")]
public DateTime LastUpdated { get; set; }
}

注意

パスカルケースの ConventionPack

このページのC# クラスはプロパティ名にパスカルケースを使用していますが、MongoDB コレクションのフィールド名はキャメルケースを使用しています。この違いを考慮するために、アプリケーションが起動する際に次のコードを使用してConventionPackを登録してください。

var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() };
ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);

次の Comment クラスは、sample_mflix.comments コレクション内のドキュメントをモデル化します。

public class Comment
{
public Guid Id { get; set; }
[BsonElement("movie_id")]
public Guid MovieId { get; set; }
public string Text { get; set; }
}

MongoDB .NET/ C#ドライバーを使用して$lookup ステージを集計パイプラインに追加するには、 オブジェクトでLookup() PipelineDefinitionメソッドを呼び出します。

次の例では、movies コレクションと comments コレクション間で左外部結合を実行するパイプラインステージを作成します。このコードは、各 Movieドキュメントの IdフィールドをComment ドキュメントの MovieIdフィールドに結合します。各映画のコメントは、各 Movieドキュメントの Comments という名前のフィールドに保存されます。

var commentCollection = client
.GetDatabase("aggregation_examples")
.GetCollection<Comment>("comments");
var pipeline = new EmptyPipelineDefinition<Movie>()
.Lookup<Movie, Movie, Comment, Movie>(
foreignCollection: commentCollection,
localField: m => m.Id,
foreignField: c => c.MovieId,
@as: m => m.Comments);

このページのNode.js の例では、Atlasサンプルデータセットsample_mflixデータベースを使用します。無料のMongoDB Atlas cluster を作成し、サンプルデータセットをロードする方法については、 MongoDB Node.jsドライバーのドキュメントの開始を参照してください。

MongoDB Node.jsドライバーを使用して $lookup ステージを集計パイプラインに追加するには、パイプラインオブジェクトで $lookup 演算子を使用します。

次の例では、movies コレクションと comments コレクションの間で左外部結合を実行するパイプラインステージを作成します。このコードは、各 movie ドキュメントの _id フィールドを comment ドキュメントの movie_id フィールドに結合します。comments フィールドは、各 movie ドキュメントの各映画に対するコメントを保存します。次に、この例は集計パイプラインを実行します。

const pipeline = [
{
$lookup: {
from: "comments",
localField: "_id",
foreignField: "movie_id",
as: "comments"
}
}
];
const cursor = collection.aggregate(pipeline);
return cursor;

戻る

$listSessions

ルール バッジを取得する

「ドキュメントモデルに関連する」を無料でマスターします。

詳細

項目一覧