Database References

在本页面

在 MongoDB 中,某些数据经过“非规范化”,或与相关数据一起存储在documents中,以消除对联接的需要。但是,在某些情况下,将相关信息存储在单独的文档中(通常存储在不同的集合或数据库中)是有意义的。

Important

从 3.2 版开始,您可以使用$lookup对同一数据库中的未分片集合执行左外部联接。

有关更多信息和示例,请参见$lookup

本页概述了$lookup管道阶段之前的替代过程。

MongoDB 应用程序使用以下两种方法之一来关联文档:

  • 将一个文档的_id字段保存在另一文档中的Manual references作为参考。然后,您的应用程序可以运行第二个查询以返回相关数据。这些参考对于大多数用例而言都是简单且足够的。

  • DBRefs是使用第一个文档的_id字段的值,集合名称以及(可选)其数据库名称从一个文档到另一个文档的引用。通过包含这些名称,DBRef 可以使位于多个集合中的文档更容易与单个集合中的文档链接。

若要解析 DBRef,您的应用程序必须执行其他查询以返回引用的文档。许多drivers具有帮助程序方法,这些方法自动形成 DBRef 的查询。驱动程序[1]不会自动将 DBRef 解析为文档。

DBRef 提供了一种通用的格式和类型来表示文档之间的关系。如果数据库必须与多个框架和工具进行交互,则 DBRef 格式还提供了表示文档之间链接的通用语义。

除非您有令人信服的理由使用 DBRef,否则请改为使用手动引用。

[1]一些社区支持的驱动程序可能会有其他行为,并且可能会自动将 DBRef 解析为文档。

Manual References

Background

使用手动引用是在另一个文档中包含一个document's _id字段的一种做法。然后,应用程序可以根据需要发出第二个查询来解析引用的字段。

Process

考虑以下操作,使用第一个文档的_id字段作为第二个文档的参考来插入两个文档:

original_id = ObjectId()

db.places.insert({
    "_id": original_id,
    "name": "Broadway Center",
    "url": "bc.example.net"
})

db.people.insert({
    "name": "Erin",
    "places_id": original_id,
    "url":  "bc.example.net/Erin"
})

然后,当查询从people集合返回文档时,您可以根据需要再次查询places集合中places_id字段引用的文档。

Use

对于几乎要在两个文档之间存储关系的每种情况,请使用manual references。引用很容易创建,您的应用程序可以根据需要解析引用。

手动链接的唯一限制是这些引用不传达数据库和集合名称。如果单个集合中的文档与多个集合中的文档相关,则可能需要考虑使用 DBRef。

DBRefs

Background

DBRef 是表示document的约定,而不是特定的引用类型。除了_id字段中的值之外,它们还包括集合的名称,在某些情况下还包括数据库的名称。

Format

DBRef 具有以下字段:

  • $ref

    • $ref字段保存引用文档所在的集合的名称。
  • $id

    • $id字段包含所引用文档中_id字段的值。
  • $db

    • Optional.

包含引用文档所在的数据库的名称。

仅某些驱动程序支持$db参考。

Example

DBRef 文档类似于以下文档:

{ "$ref" : <value>, "$id" : <value>, "$db" : <value> }

考虑来自在creator字段中存储 DBRef 的集合中的文档:

{
"_id" : ObjectId("5126bbf64aed4daf9e2ab771"),
// .. application fields
"creator" : {
"$ref" : "creators",
"$id" : ObjectId("5126bc054aed4daf9e2ab772"),
"$db" : "users"
}
}

在此示例中,DBRef 指向users数据库的creators集合中的文档,该文档的_id字段中具有ObjectId("5126bc054aed4daf9e2ab772")

Note

DBRef 中字段的 Sequences 很重要,使用 DBRef 时必须使用上述 Sequences。

DBRef 的驱动程序支持

DriverDBRef SupportNotes
CNot Supported您可以手动遍历引用。
C++Not Supported您可以手动遍历引用。
C#Supported请参阅C#驱动程序页面以获取更多信息。
HaskellNot Supported您可以手动遍历引用。
JavaSupported请参阅Java 驱动程序页面以获取更多信息。
Node.jsSupported请参阅Node.js 驱动程序页面以获取更多信息。
PerlSupported请参阅Perl 驱动程序页面以获取更多信息。
PHPNot Supported您可以手动遍历引用。
PythonSupported请参阅PyMongo 驱动程序页面以获取更多信息。
RubySupported请参阅Ruby 驱动程序页面以获取更多信息。
ScalaNot Supported您可以手动遍历引用。

Use

在大多数情况下,您应该使用manual reference方法来连接两个或更多相关文档。但是,如果需要引用多个集合中的文档,请考虑使用 DBRef。