MongoDB数据建模-第二章:使用MongoDB进行数据建模(三):设计文档

2.3设计文档

到这里,我相信你一定在问自己:如果文档的基本结构是JSON(非常简单和文本的东西),什么会导致创建NoSQL数据库如此复杂?

让我们来看看!首先,是的!你疑问是对的。NoSQL数据库可以非常简单。但是,这并不意味着它们的结构不会比关系数据库的结构复杂。不过,它会有所不同!

如前所述,集合不会强制您事先定义文档的结构。但这肯定是你必须在某个时候做出的决定。这个决定会影响重要的方面,特别是在查询的性能方面。

现在,您很可能也会问自己,这些应用程序如何表示文档之间的关系。如果你直到现在才想到这个,那不是你的错。我们习惯于思考关系世界,比如想知道学生和他们的班级之间,或者产品与订单之间的关系。

MongoDB也有自己的表示这种关系的方式。其实有两种方法:

嵌入式文档(Embeddeddocuments);

引用(Reference)。

2.3.1使用嵌入式文档

通过使用子文档,我们可以构建更复杂和优化的数据结构。因此,当我们建模文档时,我们可以选择将相关数据嵌入到一个文档中。

将数据嵌入到一个文档中的决定,通常与获得更好的读取性能的意图有关,因为使用一个查询我们可以完全检索我们需要的信息。

看下面的示例:

{

id: 1,

title: "MongoDBData Modeling Blog post",

body: "MongoDBData Modeling....",

author: "Wilsonda Rocha França",

date:ISODate("2014-11-19"),

comments: [

{

name:"Mike",

comment:"Mike comment...."

},

{

name:"Tom",

comment:"Tom comment...."

},

{

name:"Yuri",

comment:"Yuri comment...."

}

],

tags:["mongodb", "modeling", "nosql"]

}

附上述代码截图如下:

正如我们可以推论的,这个文档代表了一篇博文。这种文档的优点是,只需一个查询,我们就可以获得所有需要呈现给用户的数据。这同样适用于更新:只需一个查询,我们可以修改此文档的内容。不过,当我们决定嵌入数据时,我们必须确保文档不超过16 MB的BSON大小限制。

在MongoDB中嵌入数据时没有规则,但总的来说,我们应该观察:

•我们在文档之间是否有一对一的关系。

•文档之间是否存在一对多关系,以及关系中的"多"部分是否非常依赖于"一"部分。举例来说,这意味着每次我们展示"一"部分时,我们也会呈现这种关系的"多"部分。

如果我们的模型符合上述情况之一,我们应该考虑使用嵌入式文档。

2.3.2使用引用

规范化是帮助构建关系数据模型的基本过程。为了尽量减少冗余,在这个过程中,我们将较大的表分成较小的表并定义它们之间的关系。可以说在MongoDB中创建一个引用,是我们必须"正常化"我们模型的方式。该引用将描述文件之间的关系。

您可能会对我们为什么要考虑非关系世界中的关系感到困惑,但这并不意味着关系在NoSQL数据库中不存在。我们将经常使用关系建模的概念来解决常见问题。如前所述,为了消除冗余,文档可以互相引用。

可是等等!从现在开始你应该知道一些非常重要的事情:MongoDB不支持连接运算(joins)。这意味着,即使参考了其他文档,您也必须至少执行两次查询才能获取所需的完整信息。

看下面的例子:

{

_id: 1,

name : "Product1",

description: "Product 1description",

price: "$10,00",

supplier : {

name: "Supplier1",

address: "St.1",

}

}

{

_id: 2,

name : "Product2",

description: "Product 2description",

price: "$10,00",

supplier : {

name: "Supplier1",

address: "St.1",

}

}

{

_id: 3,

name : "Product 3",

description: "Product 3description",

price: "$10,00",

supplier : {

name: "Supplier1",

address:"St.1",

}

}

附上述代码截图如下:

在前面的例子中,我们有来自产品集合的文档。我们可以看到,在三种产品的实例中,我们对供应商密钥具有相同的价值。我们可以有两个集合:产品和供应商(products和suppliers),而不是这种重复的数据,我们可以在下面的例子中看到:

供应商(suppliers)

suppliers

{

_id: 1

name: "Supplier 1",

address: "St.1",

products: [1, 2, 3]

}

产品(products)

{

_id: 1,

name : "Product 1",

description: "Product 1 description",

price: "$10,00"

}

{

_id: 2,

name : "Product 2",

description: "Product 2 description",

price: "$10,00"

}

{

_id: 3,

name : "Product 3",

description: "Product 3 description",

price: "$10,00"

}

在这种特殊情况下,由供应商提供一些产品,参考供应商的产品选择是很好的。但是,如果情况恰恰相反,那么更好的方法是:

供应商-suppliers

{

_id: 1

name: "Supplier 1",

address: "St.1",

}

产品-products

{

_id: 1,

name : "Product 1",

description: "Product 1 description",

price: "$10,00",

supplier: 1

}

{

_id: 2,

name : "Product 2",

description: "Product 2 description",

price: "$10,00",

supplier: 1

}

{

_id: 3,

name : "Product 3",

description: "Product 3 description",

price: "$10,00",

supplier: 1

}

对于使用MongoDB的引用是没有规则的,但总的来说,我们应该注意到:

•嵌入数据时是否多次复制相同的信息(这表明读取性能不佳)

•是否需要呈现多对多的关系

•的模型是否是一个层次结构

如果我们的模型符合上述情况之一,我们应该考虑使用引用。

2.3.3原子性

设计文档时影响我们决策的另一个重要概念是原子性。在MongoDB中,操作在文档级别是原子性的。这意味着我们可以一次修改一个文档。即使我们有一个在集合(相当于表)中的多个文档中工作的操作,该操作一次只能在一个文档(一条记录-表行)中进行。(为什么?_Id唯一)

因此,当我们决定使用嵌入数据对文档进行建模时,我们只需编写操作,因为我们需要的所有数据都在同一个文档中。这与我们选择引用数据时发生的情况相反,在这种情况下,我们需要许多不是原子的写入操作。

本节设计文档的内容到此为止,下一节讲解:4.通用文档模式敬请继续阅读。

码字很辛苦,顺手就打赏点呗~^_^

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180523A148U000?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券