$lookup
The MongoDB server $lookup performs a left outer join of one unsharded collection to another unsharded collection in the same database. Lookups are useful as they allow you to filter in documents from the "joined" collection for processing.
In federated database instance, you can use $lookup
to join sharded and unsharded
collections from the same database or different databases from Atlas,
AWS S3, and HTTP or HTTPS data stores.
Note
For sharded collections, $lookup
is only
available on Atlas clusters running MongoDB 5.1 and later.
Syntax
The $lookup
syntax is
described in the MongoDB server manual.
In Data Federation, the from
field in $lookup
has the
following alternate syntax. This allows you to specify an object that
contains an optional database name and a required collection name:
{ $lookup: { localField: "<fieldName>", from: <collection-to-join>|{db: <db>, coll: <collection-to-join>}, foreignField: "<fieldName>", as: "<output-array-field>", } }
{ $lookup: { from: <collection to join>|{db: <db>, coll: <collection-to-join>}, let: { <var_1>: <expression>, …, <var_n>: <expression> }, pipeline: [ <pipeline to execute on the collection to join> ], as: <output array field> } }
from
Field Object
Field | Type | Description | Necessity |
---|---|---|---|
| string | The database name. If you specify a database name, Data Federation reads data from the collection in the specified database. If you specify a database name that differs from the database upon which the command is operating, all nested $lookup stages must also specify this database name. If you don't specify a database name within a $lookup stage, collections in the stage inherit the database name specified in the closest parent $lookup stage if it exists, or the name of the database upon which the command is operating. | Conditional |
| string | The collection name. | Required |
Examples
Suppose there are three databases named sourceDB1
, sourceDB2
, and
sourceDB3
with the following collections:
db.orders.insertMany([ { "_id" : 1, "item" : "almonds", "price" : 12, "quantity" : 2 }, { "_id" : 2, "item" : "pecans", "price" : 20, "quantity" : 1 }, { "_id" : 3 } ])
db.catalog.insertMany([ { "_id" : 1, "sku" : "almonds", "description": "product 1" }, { "_id" : 2, "sku" : "bread", "description": "product 2" }, { "_id" : 3, "sku" : "cashews", "description": "product 3" }, { "_id" : 4, "sku" : "pecans", "description": "product 4" }, { "_id" : 5, "sku": null, "description": "Incomplete" }, { "_id" : 6 } ])
db.warehouses.insertMany([ { "_id" : 1, "stock_item" : "almonds", "warehouse": "A", "instock" : 120 }, { "_id" : 2, "stock_item" : "pecans", "warehouse": "A", "instock" : 70 }, { "_id" : 3, "stock_item" : "cashews", "warehouse": "B", "instock" : 60 }, { "_id" : 4, "stock_item" : "bread", "warehouse": "B", "instock" : 80 }, { "_id" : 5, "stock_item" : "cookies", "warehouse": "A", "instock" : 80 } ])
The following examples use the $lookup aggregation stage to join documents from one collection with the documents from the collection in the other databases.
Basic Example
The following aggregation operation on the sourceDB1.orders
collection joins the documents from the orders
collection with the documents
from the sourceDB2.catalog
collection using the item
field from the orders
collection and the sku
field from the catalog
collection:
db.getSiblingDb("sourceDB1").orders.aggregate( { $lookup: { from: { db: "sourceDB2", coll: "catalog" }, localField: "item", foreignField: "sku", as: "inventory_docs" } } )
Nested Example
The following aggregation operation on the sourceDB1.orders
collection joins the documents from the orders
collection with the documents from the sourceDB2.catalog
collection and the documents from the sourceDB3.warehouses
collection using the item
field from the orders
collection, the sku
field from the catalog
collection, and the stock_item
and instock
fields from the warehouses
collection:
db.getSiblingDb("sourceDB1").orders.aggregate( [ { $lookup: { from: db: "sourceDB2", coll: "catalog", let: { "order_sku": "$item" }, pipeline: [ { $match: { $expr: { $eq: ["$sku", "$$order_sku"] } } }, { $lookup: { from: db: "sourceDB3", coll: "warehouses", pipeline: [ { $match: { $expr:{ $eq : ["$stock_item", "$$order_sku"] } } }, { $project : { "instock": 1, "_id": 0} } ], as: "wh" } }, { "$unwind": "$wh" }, { $project : { "description": 1, "instock": "$wh.instock", "_id": 0} } ], as: "inventory" }, }, ] )