MongoDB は、データをコレクションに保存する人気のある NoSQL データベースです。 MongoDB コレクションは、JSON 形式の実際のデータを含む 1 つ以上のドキュメントで構成されます。ドキュメントは従来のリレーショナル SQL データベースの行に相当し、コレクションはテーブルに相当します。
データベースの重要な機能は、データベースに保存されているデータをクエリする機能です。データをクエリすると、特定の情報の取得、データ分析、データ レポート、さらにはデータ統合が可能になります。
データベースに効果的にクエリを実行できるようにするには、複数のテーブル (SQL データベースまたは NOSQL データベースの複数のコレクションの場合) のデータを 1 つの結果セットに結合できることが重要です。
MongoDB $lookup では、ユーザーはクエリ時に 2 つのコレクションからの情報を結合します。これは、SQL データベースの左外部結合と同等の機能を実行します。
$lookup の用途と目的
データベースの重要な機能は、生データから意味のある情報を得るデータ処理です。
たとえば、レストラン ビジネスを経営している場合は、レストランのデータを分析して、毎日の収益を調べたり、週末に需要がある食品を調べたり、店で販売したコーヒーのカップ数を調べたりすることもできます。一日の各時間。
このようなニーズには、単純なデータベース クエリでは十分ではありません。保存したデータに対して高度なクエリを実行する必要があります。このようなニーズに対応するために、MongoDB には集約パイプラインと呼ばれる機能があります。
集計パイプラインは、ステージと呼ばれる構成可能な操作で構成されるシステムであり、データを処理して最終的な集計結果を生成するために使用されます。集計パイプラインのステージの例には、$sort、$match、$group、$merge、$count、$lookup などが含まれます。
これらのステージは、集約パイプライン内で任意の順序で適用できます。集約パイプラインの各段階で、集約パイプラインを通過するデータに対してさまざまな操作が実行されます。

したがって、 $lookup は MongoDB 集約パイプラインのステージの 1 つです。 $Lookup は、MongoDB データベース内の 2 つのコレクション間の左外部結合を実行するために使用されます。左外部結合は、左側のすべてのドキュメントまたはエントリを、右側の一致するドキュメントまたはエントリと結合します。
たとえば、以下の 2 つのコレクションを考えてみましょう。これらは理解しやすいように表形式で表されています。
注文コレクション :
注文ID | 顧客ID | 注文日 | 合計金額 |
---|---|---|---|
1 | 100 | 2022-05-01 | 50.00 |
2 | 101 | 2022-05-02 | 75.00 |
3 | 102 | 2022-05-03 | 100.00 |
顧客コレクション :
customer_num | 顧客名 | 顧客のメールアドレス | 顧客の電話番号 |
---|---|---|---|
100 | ジョン・ドウ | john@example.com | 555-1234 |
102 | ジェーン・スミス | ジェーン@example.com | 555-5678 |
order_collection に表示される customer_id フィールドを使用して、上記のコレクションに対して左外部結合を実行すると、 order_collection が左側のコレクションで、 Customers_collection が 右側のコレクションになります。結果には、 Orders Collection 内のすべてのドキュメントとドキュメントが含まれます。 Orders コレクション内のいずれかのレコードの customer_id と一致する customer_num を持つ Customers コレクション。
注文と顧客のコレクションに対する左外部結合操作の最終結果は、表形式で表すと次のようになります。
Orders コレクション内の customer_id 101 を持つ顧客については、Customers コレクション内に一致する customer_num 値がなく、customer テーブルから欠落している対応する値が null で埋められていることに注意してください。
$lookup は、 フィールド間の厳密な等価比較を実行し、一致したフィールドだけでなく、一致したドキュメント全体を取得します。
$lookup 構文
$lookup の構文は次のとおりです。
{
$lookup:
{
from: <collection to join>,
localField: <field from the input documents>,
foreignField: <field from the documents of the "from" collection>,
as: <output array field>
}
}
$lookup には 4 つのパラメータがあります。
- from – ドキュメントを検索するコレクションを表します。 order_collection と Customers_collection を使用した前述の例では、コレクションの from として customer_collection を配置します。
- localField – これは、 from コレクション (この場合は customer_collection ) 内のフィールドと比較するために使用する、作業コレクションまたはプライマリ コレクション内のフィールドです。上の例では、 localField は 、 orders_collection 内にある customer_id になります。
- externalField – これは、 from で指定したコレクション内で比較するフィールドです。この例では、これは customer_collection 内で見つかった customer_num になります。これを from の値として使用します。
- as – これは、ドキュメント内に表示されるフィールドを表すために指定する新しいフィールド名です。ドキュメントには、localField と externalField の間の一致の結果として得られるドキュメントが含まれます。これらすべての一致は、このフィールドの配列に入れられます。一致するものがない場合、このフィールドには空の配列が含まれます。
以前の 2 つのコレクションから、次のコードを使用して、orders_collection を作業コレクションまたはプライマリ コレクションとして 2 つのコレクションに対して $lookup 操作を実行します。
{
$lookup: {
from: "customers_collection",
localField: "customer_id",
foreignField: "customer_num",
as: "customer_info"
}
as フィールドには任意の文字列値を指定できることに注意してください。ただし、作業ドキュメントにすでに存在する名前を指定すると、そのフィールドは上書きされます。
複数のコレクションからのデータを結合する
MongoDB $lookup は 、MongoDB の集計パイプラインの便利なステージです。 MongoDB の集計パイプラインに $lookup ステージが必要という要件はありませんが、複数のコレクションにわたるデータの結合が必要な複雑なクエリを実行する場合、このステージは非常に重要です。
$lookup ステージは 2 つのコレクションに対して左外部結合を実行します。その結果、新しいフィールドが作成されるか、既存のフィールドの値が別のコレクションのドキュメントを含む配列で上書きされます。
これらのドキュメントは、比較対象のフィールドの値と一致する値があるかどうかに基づいて選択されます。最終結果は、一致が見つかった場合はドキュメントの配列を含むフィールド、一致が見つからなかった場合は空の配列を含むフィールドになります。
以下に示す従業員およびプロジェクトのコレクションを考えてみましょう。

次のコードを使用して、2 つのコレクションを結合できます。
db.projects.aggregate([
{
$lookup: {
from: "employees",
localField: "employees",
foreignField: "_id",
as: "assigned_employees"
}
}
])
この操作の結果は、2 つのコレクションを組み合わせたものになります。その結果、プロジェクトと各プロジェクトに割り当てられたすべての従業員が得られます。従業員は配列で表されます。

$lookup と併用できるパイプライン ステージ
前に述べたように、 $lookup は MongoDB 集計パイプラインのステージであり、他の集計パイプライン ステージと一緒に使用できます。これらのステージを $lookup と組み合わせて使用する方法を示すために、説明のために次の 2 つのコレクションを使用します。

MongoDB では、JSON 形式で保存されます。上記のコレクションは MongoDB では次のようになります。

$lookup と一緒に使用できる集約パイプライン ステージの例としては、次のようなものがあります。
$match
$match は、ドキュメント ストリームをフィルタリングして、指定された条件を満たすドキュメントのみが集約パイプラインの次のステージに進むことを許可するために使用される集約パイプライン ステージです。このステージは、パイプラインの早い段階で不必要なドキュメントを削除して集計パイプラインを最適化するために使用するのが最適です。
前の 2 つのコレクションを使用すると、次のように $match と $lookup を組み合わせることができます。
db.users.aggregate([
{
$match: {
country: "USA"
}
},
{
$lookup: {
from: "orders",
localField: "_id",
foreignField: "user_id",
as: "orders"
}
}
])
$match は 、米国からのユーザーをフィルターするために使用されます。 $match の結果は $lookup と組み合わされて、米国のユーザーの注文の詳細を取得します。上記の操作の結果を以下に示します。

$プロジェクト
$project は 、ドキュメントに含めるフィールド、除外するフィールド、またはドキュメントに追加するフィールドを指定してドキュメントを再構成するために使用されるステージです。たとえば、それぞれ 10 個のフィールドを持つドキュメントを処理しているが、データ処理に必要なデータがドキュメント内の 4 つのフィールドのみに含まれている場合、 $project を使用して不要なフィールドを外側にフィルタリングできます。
これにより、集約パイプラインの次のステージに不要なデータが送信されるのを避けることができます。
$lookup と $project を次のように組み合わせることができます。
db.users.aggregate([
{
$lookup: {
from: "orders",
localField: "_id",
foreignField: "user_id",
as: "orders"
}
},
{
$project: {
name: 1,
_id: 0,
total_spent: { $sum: "$orders.price" }
}
}
])
上記では、$lookup を使用してユーザーと注文コレクションを結合し、$project を使用して各ユーザーの名前と各ユーザーが費やした金額のみを表示します。 $project は、結果から _id フィールドを削除するためにも使用されます。上記の操作の結果を以下に示します。

$unwind
$unwind は 、配列フィールドを分解またはアンワインドして、配列内の各要素に新しいドキュメントを作成するために使用される集計ステージです。これは、配列フィールド値に対して集計を実行する場合に便利です。
たとえば、以下の例では、 趣味 フィールドで集計を実行したい場合、それは配列であるため実行できません。ただし、 $unwind を使用して unwind を使用し、結果のドキュメントに対して集計を実行することができます。

ユーザーと注文のコレクションを使用すると、次のように $lookup と $unwind を一緒に使用できます。
db.users.aggregate([
{
$lookup: {
from: "orders",
localField: "_id",
foreignField: "user_id",
as: "orders"
}
},
{
$unwind: "$orders"
}
])
上記のコードでは、$lookup は、orders という配列フィールドを返します。次に $unwind を使用して配列フィールドを巻き戻します。この操作の結果を以下に示します。 アリスには 2 つの注文があるため、2 回表示されていることに注目してください。

$lookup の使用例の例
データ処理を実行する場合、 $lookup は便利なツールです。たとえば、類似したデータを持つコレクションのフィールドに基づいて結合する 2 つのコレクションがあるとします。単純な $lookup ステージを使用してこれを実行し、別のコレクションから取得したドキュメントを含むプライマリ コレクションに新しいフィールドを追加できます。
以下に示すユーザーと注文のコレクションを考慮します。

$lookup を使用して 2 つのコレクションを結合すると、以下に示す結果が得られます。

$lookup を 使用して、より複雑な結合を実行することもできます。 $lookup は 、2 つのコレクションの結合を実行することに限定されません。複数の $lookup ステージを実装して、3 つ以上のコレクションに対して結合を実行できます。以下に示す 3 つのコレクションについて考えてみましょう。
以下のコードを使用して、3 つのコレクション間でより複雑な結合を実行し、行われたすべての注文と注文された製品の詳細を取得できます。
以下のコードを使用すると、まさにそれが可能になります。
db.orders.aggregate([
{
$lookup: {
from: "order_items",
localField: "_id",
foreignField: "order_id",
as: "order_items"
}
},
{
$unwind: "$order_items"
},
{
$lookup: {
from: "products",
localField: "order_items.product_id",
foreignField: "_id",
as: "product_details"
}
},
{
$group: {
_id: "$_id",
customer: { $first: "$customer" },
total: { $sum: "$order_items.price" },
products: { $push: "$product_details" }
}
}
])
上記の操作の結果を以下に示します。

結論
複数のコレクションに関係するデータ処理を実行する場合、データを結合し、複数のコレクションに格納されているデータに基づいて結論を導き出すことができる $lookup が便利です。データ処理が 1 つのコレクションだけに依存することはほとんどありません。
データから有意義な結論を引き出すには、複数のコレクションにわたるデータを結合することが重要な手順です。したがって、データをより適切に処理し、コレクション全体に保存されている生データから有意義な洞察を引き出すことができるように、MongoDB 集計パイプラインで $lookup ステージを利用することを検討してください。
いくつかの MongoDB コマンドとクエリを調べることもできます。