Mar*_*ana 47 mongoose mongodb node.js
使用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,
});
Run Code Online (Sandbox Code Playgroud)
Mongoose对象嵌套示例:
var personSchema = Schema({
_id : Number,
name : String,
stories : [storySchema]
});
var storySchema = Schema({
_creator : personSchema,
title : String,
});
Run Code Online (Sandbox Code Playgroud)
Nei*_*unn 109
关于猫鼬群体的首要理解是它不是魔术,而只是一种方便的方法,它允许您自己检索相关信息.
这个概念主要用于您决定需要将数据放在单独的集合中而不是嵌入该数据的情况,并且您的主要考虑因素通常应该是文档大小或相关信息经常更新的情况.保持嵌入式数据难以处理.
"非魔法"部分基本上是在封面下发生的事情是,当你"引用"另一个源时,populate函数对该"相关"集合进行额外的查询/查询,以便"合并"父级的那些结果您检索到的对象.你可以自己做,但方法是为了方便简化任务.显而易见的"性能"考虑是,为了检索所有信息,没有一次往返数据库(MongoDB实例).总有不止一个.
作为示例,请采用两个集合:
{
"_id": ObjectId("5392fea00ff066b7d533a765"),
"customerName": "Bill",
"items": [
ObjectId("5392fee10ff066b7d533a766"),
ObjectId("5392fefe0ff066b7d533a767")
]
}
Run Code Online (Sandbox Code Playgroud)
和项目:
{ "_id": ObjectId("5392fee10ff066b7d533a766"), "prod": "ABC", "qty": 1 }
{ "_id": ObjectId("5392fefe0ff066b7d533a767"), "prod": "XYZ", "qty": 2 }
Run Code Online (Sandbox Code Playgroud)
可以通过"引用"模型或使用populate(引擎盖下)完成的"最佳"是:
var order = db.orders.findOne({ "_id": ObjectId("5392fea00ff066b7d533a765") });
order.items = db.items.find({ "_id": { "$in": order.items } ).toArray();
Run Code Online (Sandbox Code Playgroud)
因此,为了"加入"该数据,显然"至少"有两个查询和操作.
嵌入概念本质上是MongoDB如何处理不支持"连接" 1的答案.因此,您可以尝试将"相关"数据直接嵌入使用它的文档中,而不是将数据拆分为规范化集合.这里的优点是有一个"读取"操作用于检索"相关"信息,还有一个"写入"操作点来更新"父"和"子"条目,尽管通常不可能写入"很多"孩子一次不在客户端处理"列表"或以其他方式接受"多个"写入操作,并且优选地在"批量"处理中.
然后数据看起来像这样(与上面的例子相比):
{
"_id": ObjectId("5392fea00ff066b7d533a765"),
"customerName": "Bill",
"items": [
{ "_id": ObjectId("5392fee10ff066b7d533a766"), "prod": "ABC", "qty": 1 },
{ "_id": ObjectId("5392fefe0ff066b7d533a767"), "prod": "XYZ", "qty": 2 }
]
}
Run Code Online (Sandbox Code Playgroud)
因此,实际获取数据只需要:
db.orders.findOne({ "_id": ObjectId("5392fea00ff066b7d533a765") });
Run Code Online (Sandbox Code Playgroud)
两者的优点和缺点总是在很大程度上取决于应用程序的使用模式.但一目了然:
包含嵌入数据的文档总大小通常不超过16MB的存储空间(BSON限制)或其他(作为指南)包含500或更多条目的数组.
嵌入的数据通常不需要频繁更改.因此,您可以使用来自反规范化的"重复",而不需要在多个父文档中使用相同信息更新那些"重复",只是为了调用更改.
相关数据经常与父母一起使用.这意味着如果你的"读/写"情况几乎总是需要对父和子进行"读/写",那么将数据嵌入原子操作是有意义的.
相关数据总是超过16MB BSON限制.您始终可以考虑采用"分组"的混合方法,但不能违反主文档的一般硬限制.常见的情况是"发布"和"评论",其中"评论"活动预计会非常大.
相关数据需要定期更新.或者基本上是你"规范化"的情况,因为这些数据在许多父母之间"共享",并且"相关"数据经常变化,以至于在每个"父"中更新嵌入项目是不切实际的,其中"子"项发生.更容易的情况是只引用"孩子"并进行一次更改.
读写清晰分离.如果您在阅读"父母"时可能不会总是要求"相关"信息,或者在写给孩子时不需要总是改变"父母",那么可能有充分理由将模型分开作为参考.另外,如果一般希望一次更新许多"子文档",其中这些"子文档"实际上是对另一个集合的引用,那么当数据在一个单独的数据中时,通常更有效地执行采集.
因此,对于数据建模的MongoDB文档中的任一位置,实际上都有更广泛的讨论"优点/缺点" ,其中涵盖了各种用例以及使用填充方法支持的嵌入或引用模型的方法.
希望"点数"是有用的,但通常建议考虑应用程序的数据使用模式并选择最佳选择.有"选项"嵌入"应该"是你选择MongoDB的原因,但它实际上就是你的应用程序如何"使用数据"来决定哪种方法适合你的数据建模的哪一部分(因为它不是"全有或全无")最好的.
- 请注意,由于这是最初编写的,因此MongoDB引入了
$lookup
运算符,该运算符确实在服务器上的集合之间执行"连接".出于这里一般性讨论的目的,在大多数情况下,"更好"是populate()
"一般"引起的"多个查询"开销和"多个查询",但是对于任何操作仍然存在"显着的开销"$lookup
.核心设计原则是"嵌入式"意味着"已经存在"而不是"从其他地方获取".基本上"在你的口袋里"和"在货架上"之间的差异,以及在I/O术语中通常更像是"在市中心的书架上",并且特别是远离基于网络的请求.
归档时间: |
|
查看次数: |
17303 次 |
最近记录: |