Docs 菜单
Docs 主页
/
MongoDB Manual
/ / /

使用嵌入式文档建立一对一关系模型

在此页面上

  • Overview
  • 嵌入式文档模式
  • 子集模式

本页介绍了一种数据模型,该模型使用嵌入式文档来描述连接的数据之间的一对一关系。 在单个文档中嵌入连接的数据可以减少获取数据所需的读取操作次数。 一般来说,您应该构建模式,以便应用程序在单个读取操作中接收所需的所有信息。

请考虑以下映射客户和地址关系的示例。 该示例说明了如果您需要在另一个数据实体的上下文中查看一个数据实体,则嵌入相对于引用的优势。 在 patronaddress数据之间的这种一对一关系中, address属于patron

在规范化Realm 数据模型中, address文档包含对patron文档的引用。

// patron document
{
_id: "joe",
name: "Joe Bookreader"
}
// address document
{
patron_id: "joe", // reference to patron document
street: "123 Fake Street",
city: "Faketon",
state: "MA",
zip: "12345"
}

如果经常将address数据与name信息一起检索,则在引用时,您的应用程序需要发出多个查询来解析引用。 更好的Realm 数据模型是将address数据嵌入到patron数据中,如以下文档所示:

{
_id: "joe",
name: "Joe Bookreader",
address: {
street: "123 Fake Street",
city: "Faketon",
state: "MA",
zip: "12345"
}
}

借助嵌入式数据模型,应用程序可以通过一次查询检索完整的客户信息。

嵌入式文档模式的一个潜在问题是,它可能会导致大型文档包含应用程序不需要的字段。 这些不必要的数据可能会给服务器造成额外负载,并减慢读取操作的速度。 相反,您可以使用子集模式来检索在单个数据库调用中访问最频繁的数据子集。

考虑一个显示电影信息的应用程序。 movie数据库包含具有以下模式的collection集合:

{
"_id": 1,
"title": "The Arrival of a Train",
"year": 1896,
"runtime": 1,
"released": ISODate("01-25-1896"),
"poster": "http://ia.media-imdb.com/images/M/MV5BMjEyNDk5MDYzOV5BMl5BanBnXkFtZTgwNjIxMTEwMzE@._V1_SX300.jpg",
"plot": "A group of people are standing in a straight line along the platform of a railway station, waiting for a train, which is seen coming at some distance. When the train stops at the platform, ...",
"fullplot": "A group of people are standing in a straight line along the platform of a railway station, waiting for a train, which is seen coming at some distance. When the train stops at the platform, the line dissolves. The doors of the railway-cars open, and people on the platform help passengers to get off.",
"lastupdated": ISODate("2015-08-15T10:06:53"),
"type": "movie",
"directors": [ "Auguste Lumière", "Louis Lumière" ],
"imdb": {
"rating": 7.3,
"votes": 5043,
"id": 12
},
"countries": [ "France" ],
"genres": [ "Documentary", "Short" ],
"tomatoes": {
"viewer": {
"rating": 3.7,
"numReviews": 59
},
"lastUpdated": ISODate("2020-01-09T00:02:53")
}
}

目前, movie collection 包含应用程序显示电影简单概述时不需要的多个字段,例如fullplot和评级信息。 您可以将该collection分割为两个collection,而不是将所有电影数据存储在单个collection中:

  • moviecollection包含电影的基本信息。应用程序默认加载的数据如下:

    // movie collection
    {
    "_id": 1,
    "title": "The Arrival of a Train",
    "year": 1896,
    "runtime": 1,
    "released": ISODate("1896-01-25"),
    "type": "movie",
    "directors": [ "Auguste Lumière", "Louis Lumière" ],
    "countries": [ "France" ],
    "genres": [ "Documentary", "Short" ],
    }
  • movie_details collection 包含每部电影的其他不常访问的数据:

    // movie_details collection
    {
    "_id": 156,
    "movie_id": 1, // reference to the movie collection
    "poster": "http://ia.media-imdb.com/images/M/MV5BMjEyNDk5MDYzOV5BMl5BanBnXkFtZTgwNjIxMTEwMzE@._V1_SX300.jpg",
    "plot": "A group of people are standing in a straight line along the platform of a railway station, waiting for a train, which is seen coming at some distance. When the train stops at the platform, ...",
    "fullplot": "A group of people are standing in a straight line along the platform of a railway station, waiting for a train, which is seen coming at some distance. When the train stops at the platform, the line dissolves. The doors of the railway-cars open, and people on the platform help passengers to get off.",
    "lastupdated": ISODate("2015-08-15T10:06:53"),
    "imdb": {
    "rating": 7.3,
    "votes": 5043,
    "id": 12
    },
    "tomatoes": {
    "viewer": {
    "rating": 3.7,
    "numReviews": 59
    },
    "lastUpdated": ISODate("2020-01-29T00:02:53")
    }
    }

这种方法可以提高读取性能,因为它需要应用程序减少读取的数据来满足最常见的请求。应用程序可以根据需要进行额外的数据库调用,以获取访问频率较低的数据。

提示

考虑在何处拆分数据时,应该将最常访问的数据部分放入应用程序首先加载的集合。

提示

另请参阅:

要了解如何使用子集模式对collection之间的关系进行建模,请参阅使用嵌入式文档对关系进行建模。

使用包含更频繁访问数据的较小文档可减小工作集的整体大小。这些小文档可提高读取性能,并为应用程序提供更多可用内存。

但是,了解您的应用程序及其加载数据的方式非常重要。 如果不适当地将数据拆分为多个集合,则应用程序通常需要多次访问数据库并依赖JOIN操作来检索所需的所有数据。

此外,将数据拆分为许多小集合可能会增加所需的数据库维护,因为跟踪哪些数据存储在哪个集合中可能会变得困难。

后退

文档之间的关系