我有两个系列:
每次上传都与User
相关联,我需要在查看Upload
时了解其详细信息。最佳做法是在上传记录中复制此数据,还是使用populate()从_id
引用的用户集合中提取这些详细信息?
选项1
var UploadSchema = new Schema({
_id: { type: Schema.ObjectId },
_user: { type: Schema.ObjectId, ref: 'users'},
title: { type: String },
});
选项2
var UploadSchema = new Schema({
_id: { type: Schema.ObjectId },
user: {
name: { type: String },
email: { type: String },
avatar: { type: String },
//...etc
},
title: { type: String },
});
使用“选项2”,如果Users
集合中的任何数据发生更改,我将不得不在所有关联的Upload
记录中对此进行更新。另一方面,使用“选项1”,我可以放松一下,让populate()
确保始终显示最新的用户数据。
使用populate()
的开销是否显着?这种常见情况下的最佳做法是什么?
答案 0 :(得分:16)
如果您需要查询您的用户,请保持用户一个人。如果您需要查询上传内容,请单独保留上传内容。
你应该问自己的另一个问题是:每当我需要这些数据时,我是否需要嵌入对象(反之亦然)?这些数据会被更新多少次?这个数据会读多少次?
考虑一下友情请求: 每次您需要请求时,您都需要发出请求的用户,然后将请求嵌入到用户文档中。
您也可以在嵌入对象上创建索引,搜索将是单字查询/快速/一致。
只是指向我之前关于类似问题的回复的链接: Mongo DB relations between objects
我认为这篇文章适合您http://www.mongodb.org/display/DOCS/Schema+Design
使用案例
客户/订单/订单行项目
订单应该是一个集合。客户收藏。 line-items应该是一个嵌入在订单对象中的行项目数组。
博客系统。
帖子应该是一个集合。作者可能是一个单独的集合,或者仅仅是一个电子邮件地址的帖子中的字段。注释应该是帖子中的嵌入对象以提高性能。
架构设计基础
Kyle Banker,10gen
索引&查询优化 Alvin Richards,企业工程高级总监
http://www.10gen.com/presentation/mongosf-2011/mongodb-indexing-query-optimization
**这两个视频是mongoddb上见过的最好的视频imho *
答案 1 :(得分:3)
Populate()只是一个查询。因此,无论查询是什么,开销就是模型上的find()。 此外,MongoDB的最佳实践是嵌入您可以使用的内容。它将导致更快的查询。听起来你会复制大量的数据,这会使关系(链接)处于一个好位置。
“链接”只是将ObjectId放在另一个模型的字段中。
以下是Mongo最佳实践http://www.mongodb.org/display/DOCS/Schema+Design#SchemaDesign-SummaryofBestPractices