Mongoose:populate()/ DBref还是数据重复?

时间:2011-11-01 17:07:54

标签: node.js mongodb mongoose nosql

我有两个系列:

  1. 用户
  2. 上传

  3. 每次上传都与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()的开销是否显着?这种常见情况下的最佳做法是什么?

2 个答案:

答案 0 :(得分:16)

如果您需要查询您的用户,请保持用户一个人。如果您需要查询上传内容,请单独保留上传内容。

你应该问自己的另一个问题是:每当我需要这些数据时,我是否需要嵌入对象(反之亦然)?这些数据会被更新多少次?这个数据会读多少次?

考虑一下友情请求: 每次您需要请求时,您都需要发出请求的用户,然后将请求嵌入到用户文档中。

您也可以在嵌入对象上创建索引,搜索将是单字查询/快速/一致。


只是指向我之前关于类似问题的回复的链接: Mongo DB relations between objects

我认为这篇文章适合您http://www.mongodb.org/display/DOCS/Schema+Design

使用案例

客户/订单/订单行项目

  

订单应该是一个集合。客户收藏。 line-items应该是一个嵌入在订单对象中的行项目数组。

博客系统。

  

帖子应该是一个集合。作者可能是一个单独的集合,或者仅仅是一个电子邮件地址的帖子中的字段。注释应该是帖子中的嵌入对象以提高性能。

架构设计基础

Kyle Banker,10gen

  

http://www.10gen.com/presentation/mongosf2011/schemabasics

索引&查询优化 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

链接/ DBRefs http://www.mongodb.org/display/DOCS/Database+References#DatabaseReferences-SimpleDirect%2FManualLinking