数据库引用
对于 MongoDB 中的许多使用案例,将相关数据存储在单个文档中的非规范化数据模型是最佳选择。但是,在某些情况下,需要将相关信息存储在单独的文档中,通常是不同的集合或数据库中。
重要
您可以使用 $lookup
管道阶段对同一数据库中的未分片集合执行左外连接。
您还可以使用 $graphLookup
管道阶段连接未分片集合,以执行递归搜索。
本页概述了在 $lookup
和 $graphLookup
管道阶段之前的替代程序。
您可以为以下环境中托管的部署创建数据库引用:
MongoDB Atlas:用于云中 MongoDB 部署的完全托管服务
MongoDB Enterprise:基于订阅、自我管理的 MongoDB 版本
MongoDB Community:源代码可用、免费使用且可自行管理的 MongoDB 版本
MongoDB 应用程序使用两种方法之一来关联文档:
手动引用将一个文档的
_id
字段保存在另一个文档中作为引用。应用程序会运行第二个查询以返回相关数据。对于大多数使用案例来说,这些引用简单而充分。DBRef 是指从一个文档到另一文档的引用,它们会使用第一个文档的
_id
字段的值、集合名称、数据库名称(可选)以及任意其他字段。DBRef 可让您更轻松地引用存储在多个集合或数据库中的文档。
要解析 DBRef,您的应用程序必须执行额外查询以返回参考的文档。一些 MongoDB 驱动程序提供辅助方法来使 Dbref 能够解析为文档,但这不会自动发生。
DBRefs 提供了一种通用格式和类型来表示文档之间的关系。如果您的数据库必须与多个框架和工具交互,DBRef 格式还提供了表示文档之间链接的通用语义。
除非您有令人信服的理由而要使用 DBRef,否则请使用手动引用。
手动引用
背景
手动引用是指将一个文档的_id
字段包含在另一个文档中的做法。然后,应用程序可视需要发出第二个查询,以解决所引用字段的问题。
在 MongoDB Atlas 用户界面中创建手动引用
要在 MongoDB Atlas UI 中创建手动引用,请完成以下步骤:
在 MongoDB AtlasClusters 用户界面中,转到项目的 页面。
如果尚未显示,请从导航栏的 Organizations 菜单中选择包含所需项目的组织。
如果尚未显示,请从导航栏的 Projects(项目)菜单中选择所需的项目。
如果 Clusters(数据库部署)页面尚未出现,请单击侧边栏中的 Database(数据库)。
此时会显示“集群”页面。
在 集合中添加一个文档,引用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
字段中的值,它们还包括集合的名称,在某些情况下还包括数据库名称。
作为一个可选项,DBRefs 还可以包括任意数量的其他字段。额外的字段名称必须遵循服务器版本规定的任何字段名称规则。
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。