php mongodb lookup,Mongodb v3.6 中文文档 - $lookup (aggregation) | Docs4dev

MongoDB的$lookup阶段用于在聚合框架中执行集合间的左外部联接,将数据从一个集合拉取到另一个集合中。它可以处理数组字段与标量字段的匹配,甚至支持在连接条件中使用管道来实现更复杂的查询。这个功能在3.6版本后得到了增强,允许执行不相关的子查询和多个连接条件。$lookup不仅增加了新字段到原始文档,还能够与$mergeObjects等运算符结合,以合并来自不同集合的数据。
摘要由CSDN通过智能技术生成

在本页面

Definition

$lookup

3.2 版中的新功能。

对* same *数据库中的未分片集合执行左外部联接,以过滤“联接”集合中的文档以进行处理。 $lookup阶段向每个 Importing 文档添加一个新的数组字段,其元素是“ joined”集合中的匹配文档。 $lookup阶段将这些重塑的文档传递到下一个阶段。

Syntax

$lookup阶段具有以下语法:

Equality Match

要在 Importing 文档的字段与“ joined”集合的文档的字段之间执行相等匹配,$lookup阶段具有以下语法:

{

$lookup:

{

from: ,

localField: ,

foreignField: ,

as:

}

}

$lookup接收具有以下字段的文档:

FieldDescription

from在* same *数据库中指定要执行连接的集合。 from集合无法分片。有关详细信息,请参见分片收集限制。

localField指定从 Importing 文档到$lookup阶段的字段。 $lookup从from集合的文档中对localField和foreignField执行相等匹配。如果 Importing 文档不包含localField,则$lookup会将字段视为具有null的值以进行匹配。

foreignField指定from集合中文档中的字段。 $lookup对 Importing 文档中的foreignField和localField进行相等匹配。如果from集合中的文档不包含foreignField,则$lookup会将值视为null以便进行匹配。

as指定要添加到 Importing 文档中的新数组字段的名称。新的数组字段包含来自from集合的匹配文档。如果 Importing 文档中已经存在指定的名称,则现有字段为* overwrite *。

该操作将对应于以下伪 SQL 语句:

SELECT *,

FROM collection

WHERE IN (SELECT *

FROM

WHERE = );

请参阅以下示例:

加入条件和不相关的子查询

3.6 版的新功能。

为了在两个集合之间执行不相关的子查询,并允许除单个相等匹配之外的其他联接条件,$lookup阶段具有以下语法:

{

$lookup:

{

from: ,

let: { : , …, : },

pipeline: [ ],

as:

}

}

$lookup接收具有以下字段的文档:

FieldDescription

from在* same *数据库中指定要执行连接的集合。 from集合无法分片。有关详细信息,请参见分片收集限制。

let可选的。指定在pipeline字段阶段中使用的变量。使用变量表达式访问 Importing 到$lookup阶段的文档中的字段。

pipeline无法直接访问 Importing 文档字段。而是先定义 Importing 文档字段的变量,然后在pipeline的阶段中引用变量。

要访问pipeline中的let变量,请使用$expr运算符。

Note

pipeline中的阶段可以访问let变量,包括嵌套在pipeline中的其他$lookup阶段。

|

| pipeline |指定要在联接的集合上运行的管道。 pipeline确定来自合并的集合的结果文档。要返回所有文档,请指定空管道[]。

> pipeline无法直接访问 Importing 文档字段。而是先定义 Importing 文档字段的变量,然后在pipeline的阶段中引用变量。

> 要访问pipeline中的let变量,请使用$expr运算符。

> [!NOTE|label:Note]

pipeline中的阶段可以访问let变量,包括嵌套在pipeline中的其他$lookup阶段。

|

| as |指定要添加到 Importing 文档中的新数组字段的名称。新数组字段包含from集合中的匹配文档。如果 Importing 文档中已经存在指定的名称,那么现有字段将被覆盖。

该操作将对应于以下伪 SQL 语句:

SELECT *,

FROM collection

WHERE IN (SELECT

FROM

WHERE );

请参阅以下示例:

Consideration

视图和排序规则

如果执行涉及多个视图的聚合(例如$lookup或$graphLookup),则这些视图必须具有相同的collation。

分片收集限制

在$lookup阶段,from集合不能为sharded。但是,可以对运行aggregate()方法的集合进行分片。也就是说,在下面:

db.collection.aggregate([

{ $lookup: { from: "fromCollection", ... } }

])

collection可以被分片。

fromCollection无法分片。

这样,要将分片集合与未分片集合连接在一起,可以在分片集合上运行聚合并查找未分片集合;例如。:

db.shardedCollection.aggregate([

{ $lookup: { from: "unshardedCollection", ... } }

])

或者,或者要加入多个分片集合,请考虑:

修改 Client 端应用程序以执行手动查找,而不是使用$lookup聚合阶段。

如果可能,请使用嵌入式数据模型消除加入集合的需要。

Examples

使用$ lookup 执行单一平等加入

创建包含以下文档的集合orders:

db.orders.insert([

{ "_id" : 1, "item" : "almonds", "price" : 12, "quantity" : 2 },

{ "_id" : 2, "item" : "pecans", "price" : 20, "quantity" : 1 },

{ "_id" : 3 }

])

使用以下文档创建另一个集合inventory:

db.inventory.insert([

{ "_id" : 1, "sku" : "almonds", description: "product 1", "instock" : 120 },

{ "_id" : 2, "sku" : "bread", description: "product 2", "instock" : 80 },

{ "_id" : 3, "sku" : "cashews", description: "product 3", "instock" : 60 },

{ "_id" : 4, "sku" : "pecans", description: "product 4", "instock" : 70 },

{ "_id" : 5, "sku": null, description: "Incomplete" },

{ "_id" : 6 }

])

orders集合上的以下聚合操作使用orders集合中的item字段和inventory集合中的sku字段将orders中的文档与inventory集合中的文档连接在一起:

db.orders.aggregate([

{

$lookup:

{

from: "inventory",

localField: "item",

foreignField: "sku",

as: "inventory_docs"

}

}

])

该操作返回以下文档:

{

"_id" : 1,

"item" : "almonds",

"price" : 12,

"quantity" : 2,

"inventory_docs" : [

{ "_id" : 1, "sku" : "almonds", "description" : "product 1", "instock" : 120 }

]

}

{

"_id" : 2,

"item" : "pecans",

"price" : 20,

"quantity" : 1,

"inventory_docs" : [

{ "_id" : 4, "sku" : "pecans", "description" : "product 4", "instock" : 70 }

]

}

{

"_id" : 3,

"inventory_docs" : [

{ "_id" : 5, "sku" : null, "description" : "Incomplete" },

{ "_id" : 6 }

]

}

该操作将对应于以下伪 SQL 语句:

SELECT *, inventory_docs

FROM orders

WHERE inventory_docs IN (SELECT *

FROM inventory

WHERE sku= orders.item);

对数组使用$ lookup

从 MongoDB 3.4 开始,如果localField是一个数组,则可以将数组元素与标量foreignField匹配,而无需$unwind阶段。

例如,使用以下文档创建示例集合classes:

db.classes.insert( [

{ _id: 1, title: "Reading is ...", enrollmentlist: [ "giraffe2", "pandabear", "artie" ], days: ["M", "W", "F"] },

{ _id: 2, title: "But Writing ...", enrollmentlist: [ "giraffe1", "artie" ], days: ["T", "F"] }

])

使用以下文档创建另一个集合members:

db.members.insert( [

{ _id: 1, name: "artie", joined: new Date("2016-05-01"), status: "A" },

{ _id: 2, name: "giraffe", joined: new Date("2017-05-01"), status: "D" },

{ _id: 3, name: "giraffe1", joined: new Date("2017-10-01"), status: "A" },

{ _id: 4, name: "panda", joined: new Date("2018-10-11"), status: "A" },

{ _id: 5, name: "pandabear", joined: new Date("2018-12-01"), status: "A" },

{ _id: 6, name: "giraffe2", joined: new Date("2018-12-01"), status: "D" }

])

以下聚合操作将classes集合中的文档与members集合相结合,在members字段上匹配到name字段:

db.classes.aggregate([

{

$lookup:

{

from: "members",

localField: "enrollmentlist",

foreignField: "name",

as: "enrollee_info"

}

}

])

该操作返回以下内容:

{

"_id" : 1,

"title" : "Reading is ...",

"enrollmentlist" : [ "giraffe2", "pandabear", "artie" ],

"days" : [ "M", "W", "F" ],

"enrollee_info" : [

{ "_id" : 1, "name" : "artie", "joined" : ISODate("2016-05-01T00:00:00Z"), "status" : "A" },

{ "_id" : 5, "name" : "pandabear", "joined" : ISODate("2018-12-01T00:00:00Z"), "status" : "A" },

{ "_id" : 6, "name" : "giraffe2", "joined" : ISODate("2018-12-01T00:00:00Z"), "status" : "D" }

]

}

{

"_id" : 2,

"title" : "But Writing ...",

"enrollmentlist" : [ "giraffe1", "artie" ],

"days" : [ "T", "F" ],

"enrollee_info" : [

{ "_id" : 1, "name" : "artie", "joined" : ISODate("2016-05-01T00:00:00Z"), "status" : "A" },

{ "_id" : 3, "name" : "giraffe1", "joined" : ISODate("2017-10-01T00:00:00Z"), "status" : "A" }

]

}

将$ lookup 与$ mergeObjects 一起使用

在版本 3.6 中进行了更改:MongoDB 3.6 添加了$mergeObjects运算符以将多个文档合并为一个文档

创建包含以下文档的集合orders:

db.orders.insert([

{ "_id" : 1, "item" : "almonds", "price" : 12, "quantity" : 2 },

{ "_id" : 2, "item" : "pecans", "price" : 20, "quantity" : 1 }

])

使用以下文档创建另一个集合items:

db.items.insert([

{ "_id" : 1, "item" : "almonds", description: "almond clusters", "instock" : 120 },

{ "_id" : 2, "item" : "bread", description: "raisin and nut bread", "instock" : 80 },

{ "_id" : 3, "item" : "pecans", description: "candied pecans", "instock" : 60 }

])

以下操作首先使用$lookup阶段通过item字段将两个集合合并在一起,然后在$replaceRoot中使用$mergeObjects合并来自items和orders的合并文档:

db.orders.aggregate([

{

$lookup: {

from: "items",

localField: "item", // field in the orders collection

foreignField: "item", // field in the items collection

as: "fromItems"

}

},

{

$replaceRoot: { newRoot: { $mergeObjects: [ { $arrayElemAt: [ "$fromItems", 0 ] }, "$$ROOT" ] } }

},

{ $project: { fromItems: 0 } }

])

该操作返回以下文档:

{ "_id" : 1, "item" : "almonds", "description" : "almond clusters", "instock" : 120, "price" : 12, "quantity" : 2 }

{ "_id" : 2, "item" : "pecans", "description" : "candied pecans", "instock" : 60, "price" : 20, "quantity" : 1 }

使用$ lookup 指定多个加入条件

在版本 3.6 中进行了更改:MongoDB 3.6 添加了对在联接的集合上执行管道的支持,从而允许指定多个联接条件以及不相关的子查询。

创建包含以下文档的集合orders:

db.orders.insert([

{ "_id" : 1, "item" : "almonds", "price" : 12, "ordered" : 2 },

{ "_id" : 2, "item" : "pecans", "price" : 20, "ordered" : 1 },

{ "_id" : 3, "item" : "cookies", "price" : 10, "ordered" : 60 }

])

使用以下文档创建另一个集合warehouses:

db.warehouses.insert([

{ "_id" : 1, "stock_item" : "almonds", warehouse: "A", "instock" : 120 },

{ "_id" : 2, "stock_item" : "pecans", warehouse: "A", "instock" : 80 },

{ "_id" : 3, "stock_item" : "almonds", warehouse: "B", "instock" : 60 },

{ "_id" : 4, "stock_item" : "cookies", warehouse: "B", "instock" : 40 },

{ "_id" : 5, "stock_item" : "cookies", warehouse: "A", "instock" : 80 }

])

以下操作将orders集合与warehouse集合按物料,库存数量是否足以满足 Order 数量的要求结合在一起:

db.orders.aggregate([

{

$lookup:

{

from: "warehouses",

let: { order_item: "$item", order_qty: "$ordered" },

pipeline: [

{ $match:

{ $expr:

{ $and:

[

{ $eq: [ "$stock_item", "$$order_item" ] },

{ $gte: [ "$instock", "$$order_qty" ] }

]

}

}

},

{ $project: { stock_item: 0, _id: 0 } }

],

as: "stockdata"

}

}

])

该操作返回以下文档:

{ "_id" : 1, "item" : "almonds", "price" : 12, "ordered" : 2,

"stockdata" : [ { "warehouse" : "A", "instock" : 120 }, { "warehouse" : "B", "instock" : 60 } ] }

{ "_id" : 2, "item" : "pecans", "price" : 20, "ordered" : 1,

"stockdata" : [ { "warehouse" : "A", "instock" : 80 } ] }

{ "_id" : 3, "item" : "cookies", "price" : 10, "ordered" : 60,

"stockdata" : [ { "warehouse" : "A", "instock" : 80 } ] }

该操作将对应于以下伪 SQL 语句:

SELECT *, stockdata

FROM orders

WHERE stockdata IN (SELECT warehouse, instock

FROM warehouses

WHERE stock_item= orders.item

AND instock >= orders.ordered );

See also

Uncorrelated Subquery

在版本 3.6 中进行了更改:MongoDB 3.6 添加了对在联接的集合上执行管道的支持,从而允许指定多个联接条件以及不相关的子查询。

创建包含以下文档的集合absences:

db.absences.insert([

{ "_id" : 1, "student" : "Ann Aardvark", sickdays: [ new Date ("2018-05-01"),new Date ("2018-08-23") ] },

{ "_id" : 2, "student" : "Zoe Zebra", sickdays: [ new Date ("2018-02-01"),new Date ("2018-05-23") ] },

])

使用以下文档创建另一个集合holidays:

db.holidays.insert([

{ "_id" : 1, year: 2018, name: "New Years", date: new Date("2018-01-01") },

{ "_id" : 2, year: 2018, name: "Pi Day", date: new Date("2018-03-14") },

{ "_id" : 3, year: 2018, name: "Ice Cream Day", date: new Date("2018-07-15") },

{ "_id" : 4, year: 2017, name: "New Years", date: new Date("2017-01-01") },

{ "_id" : 5, year: 2017, name: "Ice Cream Day", date: new Date("2017-07-16") }

])

以下操作将absences集合与holidays集合中的 2018 年假期信息结合在一起:

db.absences.aggregate([

{

$lookup:

{

from: "holidays",

pipeline: [

{ $match: { year: 2018 } },

{ $project: { _id: 0, date: { name: "$name", date: "$date" } } },

{ $replaceRoot: { newRoot: "$date" } }

],

as: "holidays"

}

}

])

该操作返回以下内容:

{ "_id" : 1, "student" : "Ann Aardvark", "sickdays" : [ ISODate("2018-05-01T00:00:00Z"), ISODate("2018-08-23T00:00:00Z") ],

"holidays" : [ { "name" : "New Years", "date" : ISODate("2018-01-01T00:00:00Z") }, { "name" : "Pi Day", "date" : ISODate("2018-03-14T00:00:00Z") }, { "name" : "Ice Cream Day", "date" : ISODate("2018-07-15T00:00:00Z") } ] }

{ "_id" : 2, "student" : "Zoe Zebra", "sickdays" : [ ISODate("2018-02-01T00:00:00Z"), ISODate("2018-05-23T00:00:00Z") ],

"holidays" : [ { "name" : "New Years", "date" : ISODate("2018-01-01T00:00:00Z") }, { "name" : "Pi Day", "date" : ISODate("2018-03-14T00:00:00Z") }, { "name" : "Ice Cream Day", "date" : ISODate("2018-07-15T00:00:00Z") } ] }

该操作将对应于以下伪 SQL 语句:

SELECT *, holidays

FROM absences

WHERE holidays IN (SELECT name, date

FROM holidays

WHERE year = 2018);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值