核心要点
- MongoDB,一个NoSQL数据库,在3.2版本中引入了新的
$lookup
操作符,可以在两个或多个集合上执行类似LEFT-OUTER-JOIN的操作,从而实现类似关系型数据库的数据管理。然而,此操作符仅限于聚合操作中使用,聚合操作比简单的查找查询更复杂,通常也更慢。 - MongoDB的
$lookup
操作符需要四个参数:localField
(输入文档中的查找字段)、from
(要连接的集合)、foreignField
(在from
集合中查找的字段)和as
(输出字段的名称)。此操作符可用于聚合查询中,以匹配帖子、按顺序排序、限制项目数量、连接用户数据、展平用户数组并仅返回必要的字段。 - 虽然MongoDB的
$lookup
操作符很有用,可以帮助在NoSQL数据库中管理少量关系数据,但它不能替代SQL中更强大的JOIN子句。如果在MongoDB中删除用户文档,孤儿帖子文档将保留,表明缺乏约束。因此,如果频繁使用$lookup
操作符,可能表明使用了错误的数据存储,关系型(SQL)数据库可能更适合。
感谢Julian Motz的同行评审帮助。
SQL和NoSQL数据库之间最大的区别之一是JOIN。在关系型数据库中,SQL JOIN子句允许您使用它们之间的一个公共字段来组合来自两个或多个表的行。例如,如果您有书籍和出版商的表,您可以编写如下SQL命令:
SELECT book.title, publisher.name FROM book LEFT JOIN book.publisher_id ON publisher.id;
换句话说,book表有一个publisher_id字段,它引用publisher表中的id字段。
这是实用的,因为单个出版商可以提供数千本书籍。如果我们将来需要更新出版商的详细信息,我们可以更改单个记录。数据冗余被最小化,因为我们不需要为每一本书重复出版商的信息。此技术称为规范化。
SQL数据库提供一系列规范化和约束功能,以确保维护关系。
NoSQL == No JOIN?
并非总是如此…
面向文档的数据库(如MongoDB)旨在存储非规范化数据。理想情况下,集合之间不应该有任何关系。如果相同的数据需要在两个或多个文档中,则必须重复。
这可能会令人沮丧,因为几乎没有你永远不需要关系数据的情况。幸运的是,MongoDB 3.2引入了一个新的$lookup
操作符,它可以在两个或多个集合上执行类似LEFT-OUTER-JOIN的操作。但是有一个问题…
MongoDB聚合
$lookup
仅允许在聚合操作中使用。可以将其视为一系列操作符的管道,这些操作符查询、过滤和分组结果。一个操作符的输出用作下一个操作符的输入。
聚合比简单的查找查询更难理解,并且通常运行速度较慢。但是,它们功能强大,对于复杂的搜索操作来说是一个宝贵的选项。
最好用一个例子来解释聚合。假设我们正在创建一个具有用户集合的社交媒体平台。它将每个用户的详细信息存储在单独的文档中。例如:
SELECT book.title, publisher.name FROM book LEFT JOIN book.publisher_id ON publisher.id;
我们可以根据需要添加任意数量的字段,但是所有MongoDB文档都需要一个具有唯一值的_id
字段。_id
类似于SQL主键,如果需要,将自动插入。
我们的社交网络现在需要一个帖子集合,该集合存储用户的大量有见地的更新。文档存储文本、日期、评级和在user_id
字段中引用撰写它的用户:
{ "_id": ObjectID("45b83bda421238c76f5c1969"), "name": "User One", "email": "userone@email.com", "country": "UK", "dob": ISODate("1999-09-13T00:00:00.000Z") }
我们现在想显示所有用户按时间逆序排列的最后二十个评级为“important”的帖子。每个返回的文档都应包含文本、帖子的时间以及关联用户的姓名和国家/地区。
MongoDB聚合查询传递一个管道操作符数组,这些操作符按顺序定义每个操作。首先,我们需要使用$match
过滤器从帖子集合中提取所有具有正确评级的文档:
{ "_id": ObjectID("17c9812acff9ac0bba018cc1"), "user_id": ObjectID("45b83bda421238c76f5c1969"), "date": ISODate("2016-09-05T03:05:00.123Z"), "text": "My life story so far", "rating": "important" }
我们现在必须使用$sort
操作符按时间逆序对匹配的项目进行排序:
{ "$match": { "rating": "important" } }
由于我们只需要二十个帖子,因此我们可以应用$limit
阶段,以便MongoDB只需要处理我们想要的数据:
{ "$sort": { "date": -1 } }
我们现在可以使用新的$lookup
操作符连接来自用户集合的数据。它需要一个具有四个参数的对象:
-
localField
:输入文档中的查找字段 -
from
:要连接的集合 -
foreignField
:在from
集合中查找的字段 -
as
:输出字段的名称。
因此,我们的操作符是:
{ "$limit": 20 }
这将在我们的输出中创建一个名为userinfo
的新字段。它包含一个数组,其中每个值都与用户文档匹配:
{ "$lookup": { "localField": "user_id", "from": "user", "foreignField": "_id", "as": "userinfo" } }
我们之间存在一对一的关系post.user_id
和user._id
,因为一个帖子只能有一个作者。因此,我们的userinfo
数组将永远只包含一个项目。我们可以使用$unwind
操作符将其分解成一个子文档:
"userinfo": [ { "name": "User One", ... } ]
输出现在将转换为更实用的格式,可以应用其他操作符:
{ "$unwind": "$userinfo" }
最后,我们可以使用管道中的$project
阶段返回文本、帖子的时间、用户的姓名和国家/地区:
SELECT book.title, publisher.name FROM book LEFT JOIN book.publisher_id ON publisher.id;
将所有内容放在一起
我们的最终聚合查询匹配帖子、按顺序排序、限制为最新的二十个项目、连接用户数据、展平用户数组并仅返回必要的字段。完整命令:
{ "_id": ObjectID("45b83bda421238c76f5c1969"), "name": "User One", "email": "userone@email.com", "country": "UK", "dob": ISODate("1999-09-13T00:00:00.000Z") }
结果是一个最多包含二十个文档的集合。例如:
{ "_id": ObjectID("17c9812acff9ac0bba018cc1"), "user_id": ObjectID("45b83bda421238c76f5c1969"), "date": ISODate("2016-09-05T03:05:00.123Z"), "text": "My life story so far", "rating": "important" }
太棒了!我终于可以切换到NoSQL了!
MongoDB $lookup
很有用且功能强大,但即使这个基本示例也需要一个复杂的聚合查询。它不能替代SQL中更强大的JOIN子句。MongoDB也不提供约束;如果删除用户文档,孤儿帖子文档将保留。
理想情况下,$lookup
操作符应该很少需要。如果您经常需要它,您可能使用了错误的数据存储……
如果您有关系数据,请使用关系型(SQL)数据库!
也就是说,$lookup
是MongoDB 3.2的一个受欢迎的补充。它可以克服在NoSQL数据库中使用少量关系数据时的一些更令人沮丧的问题。
关于在MongoDB NoSQL数据库中使用JOIN的常见问题解答 (FAQ)
SQL连接和MongoDB连接有什么区别?
在SQL数据库中,连接操作根据它们之间相关的列组合来自两个或多个表的行。但是,MongoDB作为NoSQL数据库,不支持传统的SQL连接。相反,MongoDB提供两种执行类似操作的方法:聚合中的$lookup
阶段和$graphLookup
阶段。这些方法允许您将来自多个集合的数据组合到单个结果集中。
MongoDB中的$lookup
阶段是如何工作的?
MongoDB中的$lookup
阶段允许您连接来自另一个集合(“已连接”集合)的文档,并将已连接的文档添加到输入文档中。$lookup
阶段指定“from”集合、“localField”和“foreignField”用于匹配文档,以及“as”字段用于输出文档。它类似于SQL中的左外连接,返回来自输入集合的所有文档以及来自“from”集合的匹配文档。
我可以使用MongoDB连接执行递归搜索吗?
是的,MongoDB为递归搜索提供了$graphLookup
阶段。$graphLookup
阶段对指定的集合执行递归搜索,并可以选择限制搜索的深度和广度。它对于查询分层数据或图很有用,其中级别数未知或可能变化。
如何在使用MongoDB连接时优化性能?
为了在使用MongoDB连接时优化性能,请考虑以下策略:对“localField”和“foreignField”使用索引以加快匹配过程;限制“from”集合中的文档数量;以及在$lookup
阶段之前使用$match
和$project
阶段来过滤和转换文档。
我可以在MongoDB中连接多个集合吗?
是的,您可以通过在聚合管道中链接多个$lookup
阶段来连接多个MongoDB集合。每个$lookup
阶段都会将来自另一个集合的已连接文档添加到输入文档中。
在使用MongoDB连接时,如何处理空值或缺失值?
在使用MongoDB连接时,如果输入集合中的文档与“from”集合中的任何文档都不匹配,则$lookup
阶段会向“as”字段添加一个空数组。您可以通过在$lookup
阶段之后添加$match
阶段来处理这些空值或缺失值,以过滤掉具有空“as”字段的文档。
我可以将MongoDB连接与分片集合一起使用吗?
从MongoDB 3.6开始,$lookup
和$graphLookup
阶段可以接受分片集合作为“from”集合。但是,由于额外的网络开销,性能可能不如非分片集合。
如何对MongoDB中的已连接文档进行排序?
您可以通过在聚合管道中的$lookup
阶段之后添加$sort
阶段来对MongoDB中的已连接文档进行排序。$sort
阶段按升序或降序对指定字段中的文档进行排序。
我可以将MongoDB连接与find()
方法一起使用吗?
不可以,MongoDB连接不能与find()
方法一起使用。$lookup
和$graphLookup
阶段是聚合框架的一部分,它提供比find()
方法更高级的数据处理功能。
如何调试或排除MongoDB连接故障?
要调试或排除MongoDB连接故障,您可以使用explain()
方法来分析聚合管道的执行计划。explain()
方法提供有关阶段的详细信息,包括处理的文档数量、花费的时间以及索引的使用情况。
以上是在MongoDB NOSQL数据库中使用加入的详细内容。更多信息请关注PHP中文网其他相关文章!

该试点程序是CNCF(云本机计算基础),安培计算,Equinix金属和驱动的合作,简化了CNCF GitHub项目的ARM64 CI/CD。 该计划解决了安全问题和绩效

此基于GO的网络漏洞扫描仪有效地确定了潜在的安全弱点。 它利用了GO的并发功能的速度功能,包括服务检测和漏洞匹配。让我们探索它的能力和道德

网站建设只是第一步:SEO与反向链接的重要性 建立网站只是将其转化为宝贵营销资产的第一步。您需要进行SEO优化,以提高网站在搜索引擎中的可见度,吸引潜在客户。反向链接是提升网站排名的关键,它向谷歌和其他搜索引擎表明您的网站权威性和可信度。 并非所有反向链接都有利:识别并避免有害链接 并非所有反向链接都有益。有害链接会损害您的排名。优秀的免费反向链接检查工具可以监控链接到您网站的来源,并提醒您注意有害链接。此外,您还可以分析竞争对手的链接策略,从中学习借鉴。 免费反向链接检查工具:您的SEO情报员


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

禅工作室 13.0.1
功能强大的PHP集成开发环境

SublimeText3 英文版
推荐:为Win版本,支持代码提示!

Dreamweaver CS6
视觉化网页开发工具

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

VSCode Windows 64位 下载
微软推出的免费、功能强大的一款IDE编辑器