当前位置: 首页 > 数据应用 > MongoDB

MongoDB中如何使用$lookup实现两个集合的关联查询

时间:2023-07-02 16:54:19 MongoDB

MongoDB是一种非关系型数据库,它以文档的形式存储数据,每个文档都有一个唯一的_id字段作为主键。MongoDB中的文档可以分组存放在不同的集合(collection)中,每个集合可以有不同的结构和索引。有时候,我们需要根据某些条件从不同的集合中查询出相关的文档,这就是两个集合的关联查询。

在关系型数据库中,我们可以使用JOIN语句来实现两个表的关联查询,但是MongoDB没有提供类似的语法。那么,在MongoDB中如何实现两个集合的关联查询呢?答案是使用$lookup操作符。

$lookup操作符是MongoDB中聚合管道(aggregation pipeline)的一个阶段,它可以让一个集合引用另一个集合中的文档,从而实现类似于JOIN的效果。$lookup操作符有以下四个参数:

1.from:指定要引用的另一个集合的名称

2.localField:指定本地集合中用于匹配的字段

3.foreignField:指定引用集合中用于匹配的字段

4.as:指定输出结果中包含引用文档的字段名称

例如,假设我们有两个集合,orders和customers,分别存储订单和客户信息,如下所示:

如果我们想要查询每个订单对应的客户信息,我们可以使用以下聚合管道:

输出结果如下:

可以看到,每个订单文档都增加了一个名为customer的数组字段,包含了匹配到的客户文档。如果没有匹配到任何客户文档,那么该字段将为空数组。

$lookup操作符可以实现简单的一对一或一对多的关联查询,但是如果我们需要实现更复杂的逻辑,例如多对多的关联查询,或者根据多个字段进行匹配,或者引用集合中的子文档,那么我们需要使用$lookup操作符的扩展语法,即使用let和pipeline参数。

let参数可以让我们定义一个变量,用于存储本地集合中的一个或多个字段的值,然后在pipeline参数中使用$expr操作符来引用该变量。pipeline参数可以让我们定义一个子聚合管道,用于对引用集合进行过滤和转换。例如,假设我们有两个集合,books和authors,分别存储书籍和作者信息,如下所示:

如果我们想要查询每本书对应的作者的姓名和出生年份,我们可以使用以下聚合管道:

输出结果如下:

可以看到,每本书文档都增加了一个名为authors的数组字段,包含了匹配到的作者文档的姓名和出生年份。我们使用了let参数来定义一个变量book_authors,用于存储本地集合中的authors字段的值,然后在pipeline参数中使用$expr操作符来引用该变量,并使用$in操作符来判断引用集合中的_id字段是否在该变量中。我们还使用了$project操作符来只保留引用集合中的name和birth_year字段。