对于大多数MongoDB使用案例,非规范化数据模型会将相关数据存储在单个 文档中。在某些情况下,您需要将相关信息存储在单独的文档中,通常是不同的集合或数据库中。
重要
您可以使用 $lookup 管道阶段对同一数据库中的未分片集合执行左外连接。
您还可以使用 $graphLookup 管道阶段连接未分片集合,以执行递归搜索。
本页概述了在 $lookup 和 $graphLookup 管道阶段之前的替代程序。
MongoDB 应用程序使用两种方法之一来关联文档:
手动引用将一个文档的
_id字段保存在另一个文档中作为引用。应用程序会运行第二个查询以返回相关数据。对于大多数使用案例来说,这些引用简单而充分。DBRef 是指使用第一个文档的
_id字段的值、集合名称、数据库名称(可选)以及任何其他字段从一个文档到另一个文档的引用。DBRef 允许您引用存储在多个集合或数据库中的文档。
要解析 DBRef,应用程序必须执行额外查询以返回引用的文档。某些MongoDB驱动程序提供了将 DBRef 解析为文档的辅助方法,但解析不是自动进行的。
DBRef 提供了一种通用格式和类型来表示文档之间的关系。当数据库与多个框架和工具交互时,该格式还提供了表示文档之间链接的通用语义。
除非您有令人信服的理由而要使用 DBRef,否则请使用手动引用。
手动引用
背景
手动引用在另一个文档中包含一个文档的 _id字段。然后,应用程序可以根据需要运行第二个查询来解析引用的字段。
在 MongoDB Atlas 用户界面中创建手动引用
要在 MongoDB Atlas UI 中创建手动引用,请完成以下步骤:
在MongoDB Atlas用户界面中,转到项目的 Clusters 页面。
如果尚未显示,请从导航栏上的 Organizations 菜单中选择包含所需项目的组织。
如果尚未显示,请从导航栏的 Projects 菜单中选择您的项目。
在侧边栏中,单击 Database 标题下的 Clusters。
会显示集群页面。
在 people 集合中添加一个文档,引用 places 中的条目。
在左侧导航窗格中,选择其他集合。此示例引用
people集合。单击 Insert Document(连接)。
单击 JSON 视图图标({{}})。
将以下数据粘贴到文档中:
{ "_id": { "$oid": "651aebeb70299b120736f443" }, "name": "Erin", "places_id": "651aea5870299b120736f442" "url": "bc.example.net/Erin" } 单击 Insert(连接)。
当查询从
people集合返回文档时,您可以根据需要从places集合中筛选查询结果,以查找places_id字段引用的文档。要了解在 MongoDB Atlas 中运行查询的更多信息,请参阅 MongoDB Atlas 文档中的查看、过滤文档以及对其进行排序。
在终端中创建手动引用
比如说,以下操作会插入两个文档,使用第一个文档的 _id 字段作为第二个文档中的引用:
original_id = ObjectId() db.places.insertOne({ "_id": original_id, "name": "Broadway Center", "url": "bc.example.net" }) db.people.insertOne({ "name": "Erin", "places_id": original_id, "url": "bc.example.net/Erin" })
然后,当查询从 people 集合返回此文档时,可按需对 places 集合中的 places_id 字段引用的文档进行第二次查询。
使用
对于要存储两个文档之间关系的几乎所有情况,请使用手动引用。它们创建起来很简单,应用程序可以根据需要解决它们。
手动引用不会传达数据库和集合名称。如果单个集合中的文档与多个集合中的文档相关,请考虑使用 DBRef。
DBRef
背景
DBRef 是一种表示文档的规则,而不是一种特定的引用类型。除了_id字段中的值,它们还包括集合的名称,在某些情况下还包括数据库名称。
或者,DBRef 可以包含任意数量的其他字段。额外字段名称必须遵循服务器版本规定的字段名称规则。
format
DBRef 具有以下字段:
$ref$ref字段包含被引用文档所在集合的名称。
$id$id字段包含引用文档中_id字段的值。
$db可选。
包含被引用文档所在数据库的名称。
例子
DBRef 文档与以下文档类似:
{ "$ref" : <value>, "$id" : <value>, "$db" : <value> }
以某一集合中的某一文档为例,该文档已在 creator 字段中存储 DBRef:
{ "_id" : ObjectId("5126bbf64aed4daf9e2ab771"), // .. application fields "creator" : { "$ref" : "creators", "$id" : ObjectId("5126bc054aed4daf9e2ab772"), "$db" : "users", "extraField" : "anything" } }
此示例中的 DBRef 指向 users 数据库的 creators 集合中的一个文档,该文档的 _id 字段中包含 ObjectId("5126bc054aed4daf9e2ab772")。它还包含一个可选字段。
注意
DBRef 中的字段顺序十分重要,因而在使用 DBRef 时必须使用上述顺序。
驱动程序对 DBRef 的支持情况
驱动 | DBRef 支持 | 注意 |
|---|---|---|
C | 不受支持 | 您可以手动遍历引用。 |
C++ | 不受支持 | 您可以手动遍历引用。 |
C# | 受支持 | 有关更多信息,请参阅C#驱动程序页面。 |
Go | 不受支持 | 您可以手动遍历引用。 |
Haskell | 不受支持 | 您可以手动遍历引用。 |
Java | 受支持 | 有关更多信息,请参阅Java 驱动程序页面。 |
Node.js | 受支持 | 有关更多信息,请参阅Node.js驱动程序页面。 |
Perl | 受支持 | 有关详细信息,请参阅Perl 驱动程序页面。 |
PHP | 不受支持 | 您可以手动遍历引用。 |
Python | 受支持 | 有关更多信息,请参阅PyMongo驱动程序页面。 |
Ruby | 受支持 | 有关更多信息,请参阅Ruby 驱动程序页面。 |
Scala | 不受支持 | 您可以手动遍历引用。 |
使用
在大多数情况下,使用手册引用来连接两个或多个相关文档。如果需要引用多个集合中的文档,请考虑使用 DBRef。