View a markdown version of this page

$lookup - Amazon DocumentDB

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

$lookup

Amazon DocumentDB $lookup 中的彙總階段可讓您在兩個集合之間執行左側外部聯結。此操作可讓您根據相符的欄位值,合併來自多個集合的資料。當您需要將相關集合的資料納入查詢結果時,此功能特別有用。

參數

  • from:要執行聯結的集合名稱。

  • localField:輸入文件中要與 相符的欄位foreignField。

  • foreignField:集合中from要比對之文件的欄位localField。

  • as:要新增至輸出文件的新欄位名稱,其中包含來自from集合的相符文件。

  • pipeline:如果指定 localField和 foreignField ,則為選用。要在from集合上執行的彙總管道。管道會從from集合傳回文件。若要傳回所有文件,請指定空管道 []。管道不能包含 $out或 $merge階段。請參閱 聯結條件和相關子查詢 (MongoDB Shell)。

  • let:選用。定義要在pipeline階段中使用的變數的文件。使用變數表達式,從加入 的輸入文件中存取欄位pipeline。若要在管道階段中參考變數,請使用 "$$<variable>" 語法。請參閱 聯結條件和相關子查詢 (MongoDB Shell)。

範例 (MongoDB Shell)

下列範例示範將資料從orders集合加入customers集合的簡單$lookup操作。

建立範例文件

db.customers.insertMany([ { _id: 1, name: "Alice" }, { _id: 2, name: "Bob" }, { _id: 3, name: "Charlie" } ]); db.orders.insertMany([ { _id: 1, customer_id: 1, total: 50 }, { _id: 2, customer_id: 1, total: 100 }, { _id: 3, customer_id: 2, total: 75 } ]);

查詢範例

db.customers.aggregate([ { $lookup: { from: "orders", localField: "_id", foreignField: "customer_id", as: "orders" } } ]);

輸出

[ { _id: 1, name: 'Alice', orders: [ { _id: 2, customer_id: 1, total: 100 }, { _id: 1, customer_id: 1, total: 50 } ] }, { _id: 3, name: 'Charlie', orders: [] }, { _id: 2, name: 'Bob', orders: [ { _id: 3, customer_id: 2, total: 75 } ] } ]

聯結條件和相關子查詢 (MongoDB Shell)

8.0.2 版的新功能。

除了單一等式比對之外,Amazon DocumentDB $lookup中的 也可以在聯結的集合上執行彙總管道。這支援不相關的子查詢,其會針對每個輸入文件執行相同的子查詢,並使用每個輸入文件欄位中定義的變數傳回與該文件相關的結果。

語法

若要執行關聯的子查詢,請使用 從輸入文件的欄位定義變數let,並在pipeline階段中參考變數:

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

參數

  • let:從輸入文件的欄位定義變數的文件。若要在管道階段中參考變數,請使用 "$$<variable>" 語法。變數可由 中的階段存取pipeline,包括 中巢狀的其他$lookup階段pipeline。$match 階段需要使用 $expr 運算子來存取變數。省略 let 以執行不相關的子查詢。

  • pipeline:要在from集合上執行的彙總管道。管道無法直接存取輸入文件的欄位;使用 定義變數let,並參考變數。若要傳回所有文件,請指定空管道 []。

將聯結from集合的欄位與let變數或常數進行比較時$eq,放置在$match階段內$expr運算子中的 $gt$gte、$lt、、 和 $lte 比較運算子可以在集合上使用索引。

建立範例文件

db.customers.insertMany([ { _id: 1, name: "Alice", min_total: 60 }, { _id: 2, name: "Bob", min_total: 50 }, { _id: 3, name: "Charlie", min_total: 20 } ]); db.orders.insertMany([ { _id: 1, customer_id: 1, total: 50 }, { _id: 2, customer_id: 1, total: 100 }, { _id: 3, customer_id: 2, total: 75 } ]);

查詢範例

下列範例會將每位客戶與其訂單聯結,並僅保留total大於或等於該客戶自有min_total價值的訂單。聯結條件和每個客戶篩選 內的兩個參考let變數$expr:

db.customers.aggregate([ { $lookup: { from: "orders", let: { customer_id: "$_id", min_total: "$min_total" }, pipeline: [ { $match: { $expr: { $and: [ { $eq: [ "$customer_id", "$$customer_id" ] }, { $gte: [ "$total", "$$min_total" ] } ] } } }, { $project: { _id: 0, total: 1 } } ], as: "qualifying_orders" } } ]);

輸出

[ { _id: 1, name: 'Alice', min_total: 60, qualifying_orders: [ { total: 100 } ] }, { _id: 2, name: 'Bob', min_total: 50, qualifying_orders: [ { total: 75 } ] }, { _id: 3, name: 'Charlie', min_total: 20, qualifying_orders: [] } ]

對於每個客戶,會使用該客戶的 _id和 min_total值評估子查詢,因此每個文件都會收到自己的相關結果。

使用簡潔語法 (MongoDB Shell) 關聯子查詢

8.0.2 版的新功能。

Amazon DocumentDB 也支援簡潔相關的子查詢語法,該語法結合了 localField和 上的等式比對foreignField與 pipeline。簡潔語法會移除在$match階段中的$expr運算子內表達等式比對的需求。

語法

{ $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> } }

查詢範例

下列範例會傳回與先前相關子查詢範例相同的結果。_id 與 之間的等式比對customer_id會以 localField和 表示,foreignField而非$expr條件:

db.customers.aggregate([ { $lookup: { from: "orders", localField: "_id", foreignField: "customer_id", let: { min_total: "$min_total" }, pipeline: [ { $match: { $expr: { $gte: [ "$total", "$$min_total" ] } } }, { $project: { _id: 0, total: 1 } } ], as: "qualifying_orders" } } ]);

輸出

[ { _id: 1, name: 'Alice', min_total: 60, qualifying_orders: [ { total: 100 } ] }, { _id: 2, name: 'Bob', min_total: 50, qualifying_orders: [ { total: 75 } ] }, { _id: 3, name: 'Charlie', min_total: 20, qualifying_orders: [] } ]

相關子查詢中支援的階段

當$lookup管道使用 時let,下列階段可以參考"$$<variable>"變數:

  • $match (使用 $expr運算子)

  • $project

  • $addFields

  • $set

  • $group

  • $bucket

  • $bucketAuto

  • $sortByCount

  • $lookup (巢狀)

  • $graphLookup

不會評估變數表達式的階段,例如 $sort、、$skip$limit$count、$unwind、、 $sample和 $unset,也可以在管道中使用,但無法參考變數。

使用 let$facet、、$redact、$replaceRoot、$replaceWith、$fill、、 $geoNear $setWindowFields和 $match搭配 的$lookup管道不支援下列階段$text。

限制

  • pipeline 不能包含 $out或 $merge階段。

程式碼範例

若要檢視使用 $lookup命令的程式碼範例,請選擇您要使用的語言標籤:

Node.js
const { MongoClient } = require('mongodb'); async function example() { const client = await MongoClient.connect('mongodb://<username>:<password>@<cluster-endpoint>:27017/?tls=true&tlsCAFile=global-bundle.pem&replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false'); await client.connect(); const db = client.db('test'); const result = await db.collection('customers').aggregate([ { $lookup: { from: 'orders', localField: '_id', foreignField: 'customer_id', as: 'orders' } } ]).toArray(); console.log(JSON.stringify(result, null, 2)); await client.close(); } example();
Python
from pymongo import MongoClient def example(): client = MongoClient('mongodb://<username>:<password>@<cluster-endpoint>:27017/?tls=true&tlsCAFile=global-bundle.pem&replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false') db = client.test collection = db.customers pipeline = [ { "$lookup": { "from": "orders", "localField": "_id", "foreignField": "customer_id", "as": "orders" } } ] result = collection.aggregate(pipeline) for doc in result: print(doc) client.close() example()

相關子查詢程式碼範例

若要檢視搭配相關子查詢 (使用 let和 pipeline) 使用$lookup階段的程式碼範例,請選擇您要使用的語言標籤:

Node.js
const { MongoClient } = require('mongodb'); async function example() { const client = await MongoClient.connect('mongodb://<username>:<password>@<cluster-endpoint>:27017/?tls=true&tlsCAFile=global-bundle.pem&replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false'); const db = client.db('test'); const customers = db.collection('customers'); await customers.insertMany([ { _id: 1, name: "Alice", min_total: 60 }, { _id: 2, name: "Bob", min_total: 50 }, { _id: 3, name: "Charlie", min_total: 20 } ]); const orders = db.collection('orders'); await orders.insertMany([ { _id: 1, customer_id: 1, total: 50 }, { _id: 2, customer_id: 1, total: 100 }, { _id: 3, customer_id: 2, total: 75 } ]); // Correlated subquery: filter each customer's orders with a per-customer threshold const result = await customers.aggregate([ { $lookup: { from: 'orders', localField: '_id', foreignField: 'customer_id', let: { min_total: '$min_total' }, pipeline: [ { $match: { $expr: { $gte: [ '$total', '$$min_total' ] } } }, { $project: { _id: 0, total: 1 } } ], as: 'qualifying_orders' } } ]).toArray(); console.log(JSON.stringify(result, null, 2)); await client.close(); } example();
Python
from pymongo import MongoClient def example(): client = MongoClient('mongodb://<username>:<password>@<cluster-endpoint>:27017/?tls=true&tlsCAFile=global-bundle.pem&replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false') db = client.test customers = db.customers customers.insert_many([ { "_id": 1, "name": "Alice", "min_total": 60 }, { "_id": 2, "name": "Bob", "min_total": 50 }, { "_id": 3, "name": "Charlie", "min_total": 20 } ]) orders = db.orders orders.insert_many([ { "_id": 1, "customer_id": 1, "total": 50 }, { "_id": 2, "customer_id": 1, "total": 100 }, { "_id": 3, "customer_id": 2, "total": 75 } ]) # Correlated subquery: filter each customer's orders with a per-customer threshold pipeline = [ { "$lookup": { "from": "orders", "localField": "_id", "foreignField": "customer_id", "let": { "min_total": "$min_total" }, "pipeline": [ { "$match": { "$expr": { "$gte": [ "$total", "$$min_total" ] } } }, { "$project": { "_id": 0, "total": 1 } } ], "as": "qualifying_orders" } } ] result = customers.aggregate(pipeline) for doc in result: print(doc) client.close() example()