mongoose填充vs对象嵌套

使用mongoose种群和直接目标包含之间是否有任何性能差异(查询的处理时间)? 什么时候应该使用?

mongoose群体例子:

var personSchema = Schema({ _id : Number, name : String, stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }] }); var storySchema = Schema({ _creator : { type: Number, ref: 'Person' }, title : String, }); 

mongoose对象嵌套示例:

 var personSchema = Schema({ _id : Number, name : String, stories : [storySchema] }); var storySchema = Schema({ _creator : personSchema, title : String, }); 

首先要了解的mongoose人口是,它不是魔术,但只是一个方便的方法,让您检索相关信息,而不是自己动手。

这个概念本质上是用于你决定需要将数据放在一个单独的集合中而不是embedded这些数据的地方,而且你的主要考虑因素通常应该是文档大小,或者这些相关的信息需要经常更新维护embedded式数据笨拙。

“不神奇”的部分是,本质上发生的是,当你“引用”另一个源时,填充函数对该“相关”集合进行额外的查询/查询,以便“合并”父项的结果你已经检索的对象。 你可以自己做这个,但是这个方法是为了方便简化任务。 显而易见的“性能”考虑是,为了检索所有的信息,不需要往返数据库(MongoDB实例)。 总有不止一个。

作为一个例子,拿两个集合:

 { "_id": ObjectId("5392fea00ff066b7d533a765"), "customerName": "Bill", "items": [ ObjectId("5392fee10ff066b7d533a766"), ObjectId("5392fefe0ff066b7d533a767") ] } 

和项目:

 { "_id": ObjectId("5392fee10ff066b7d533a766"), "prod": "ABC", "qty": 1 } { "_id": ObjectId("5392fefe0ff066b7d533a767"), "prod": "XYZ", "qty": 2 } 

可以通过“引用”模型或使用填充(在引擎盖下)完成的“最佳”是这样的:

 var order = db.orders.findOne({ "_id": ObjectId("5392fea00ff066b7d533a765") }); order.items = db.items.find({ "_id": { "$in": order.items } ).toArray(); 

因此,为了“join”数据,显然存在“至less”两个查询和操作。

embedded的概念本质上是MongoDB如何处理不支持“连接”的答案。 所以相反,将数据分割成规范化的集合,你试图直接在使用它的文档中embedded“相关”数据。 这样做的好处是有一个单一的“读取”操作来检索“相关”信息,还有一个单独的“写入”操作来更新“父”和“子”项,尽pipe通常不可能写入“许多”孩子一次不处理客户端上的“列表”或以其他方式接受“多个”写入操作,并且优选地在“批量”处理中。

然后数据看起来像这样(与上面的例子相比):

 { "_id": ObjectId("5392fea00ff066b7d533a765"), "customerName": "Bill", "items": [ { "_id": ObjectId("5392fee10ff066b7d533a766"), "prod": "ABC", "qty": 1 }, { "_id": ObjectId("5392fefe0ff066b7d533a767"), "prod": "XYZ", "qty": 2 } ] } 

因此实际提取数据只是一个问题:

 db.orders.findOne({ "_id": ObjectId("5392fea00ff066b7d533a765") }); 

两者的优缺点总是在很大程度上取决于您的应用程序的使用模式。 但是一目了然:

embedded

  • 带有embedded数据的文档总大小通常不超过16MB(BSON限制),否则(作为指导)具有包含500个或更多条目的数组。

  • embedded的数据通常不需要频繁更改。 所以,你可以忍受来自非规范化的“重复”,而不会导致需要用许多父文档中的相同信息来更新这些“重复”,而只是为了调用一个更改。

  • 相关数据经常与父母关联使用。 这意味着,如果你的“读/写”情况几乎总是需要“读/写”给父母和孩子,那么embedded数据用于primefaces操作是有意义的。

引用

  • 相关的数据总是会超过16MB的BSON限制。 你总是可以考虑采用混合的方法,但主文档的一般硬限制是不能被破坏的。 常见的情况是“发表”和“评论”,其中“评论”活动预计会非常大。

  • 相关数据需要定期更新。 或者基本上是“正常化”的情况,因为这些数据在许多父母中是“共享的”,并且“相关”数据经常变化,以至于在“子”项出现的每个“父”中更新embedded的项目是不切实际的。 更简单的情况是只参考“孩子”,并做一次改变。

  • 读写有明显的分离。 如果您在阅读“父母”时并不总是要求“相关”信息,或者在写信给孩子时不需要经常更改“父母”,那么可能有充分的理由分开模型作为参考。 此外,如果一般希望一次更新许多“子文件”,其中这些“子文件”实际上是对另一个集合的引用,那么当数据处于单独的数据时,实施通常更有效采集。

因此,实际上MongoDB 数据build模文档中的任何一个位置的“优点/缺点”的讨论更广泛,其中讨论了各种使用情况以及如何使用embedded或引用模型来处理填充方法所支持的方法。

希望“点”是有用的,但一般build议是考虑您的应用程序的数据使用模式,并select最好的。 有“选项”embedded“应该”是你selectMongoDB的原因,但它实际上是你的应用程序“使用数据”,决定哪种方法适合于你的数据build模的哪一部分(因为它不是“全部或全部”)最好。