2015-10-24 93 views
1

我最近开始使用mongodb和nodejs构建一个宁静的web服务。不幸的是,mongodb对我来说是非常新的,来自关系数据库世界,我向自己提出了很多问题。

让我来向您解释我的问题: 目标是构建一种具有社交功能的内容管理系统,例如用户可以发布可共享和评论的主题。 我有两种可能性,一种是使用引用来获取用户发布的主题,另一种使用主题作为用户的嵌入文档而不是引用。

所以基本上我能有这2种模式:

var UserSchema = new Schema({ 
 
    username: { 
 
    type: String, 
 
    unique: true, 
 
    required: true 
 
    }, 
 
    password: { 
 
    type: String, 
 
    required: true 
 
    }, 
 
    name: { 
 
    type: String 
 
    }, 
 
    first_name: String, 
 
    phone: String, 
 
    topics: [Topic.schema] 
 
}); 
 
var TopicSchema = new Schema({ 
 
    _creator: { 
 
    type: String, 
 
    ref: 'User' 
 
    }, 
 
    description: String, 
 
    comments: [Comments.schema], 
 
    shared_with: [{ 
 
     type: Schema.ObjectId, 
 
     ref: 'User' 
 
    }] //[{ type: String, ref: 'User'}] 
 
}); 
 
var CommentSchema = new Schema({ 
 
    _creator: { 
 
    type: String, 
 
    require: true 
 
    }, 
 
    text: { 
 
    type: String, 
 
    required: true 
 
    }, 
 
});

var UserSchema = new Schema({ 
 
    username: { 
 
    type: String, 
 
    unique: true, 
 
    required: true 
 
    }, 
 
    password: { 
 
    type: String, 
 
    required: true 
 
    }, 
 
    name: { 
 
    type: String 
 
    }, 
 
    first_name: String, 
 
    phone: String, 
 
    topics: [{ type: Schema.ObjectId, ref: 'Topics'}] 
 
}); 
 
var TopicSchema = new Schema({ 
 
    _creator: { 
 
    type: String, 
 
    ref: 'User' 
 
    }, 
 
    description: String, 
 
    comments: [Comments.schema], 
 
    shared_with: [{ 
 
     type: Schema.ObjectId, 
 
     ref: 'User' 
 
    }] //[{ type: String, ref: 'User'}] 
 
}); 
 
var CommentSchema = new Schema({ 
 
    _creator: { 
 
    type: String, 
 
    require: true 
 
    }, 
 
    text: { 
 
    type: String, 
 
    required: true 
 
    }, 
 
});

所以第一个模式使用1个合作选择用户文档,为用户选择第二个使用集合,为主题选择第一个集合,这意味着例如可以找到2个查询来检索用户及其主题,但也可以直接查询主题。

这里是要求我使用的检索与第一架构的一些用户信息特定主题:

User.aggregate([ 
    {$match: { 
     "topics._id":{$in:[mongoose.Types.ObjectId('56158c314861d2e60d000003')]} 
    }}, 
    { $unwind:"$topics" }, 
    {$match: { 
     "topics._id":{$in:[mongoose.Types.ObjectId('56158c314861d2e60d000003')]} 
    }}, 
    { $group: { 
     _id: { 
      _id:"$_id", 
      name:"$name", 
      first_name:"$first_name" 
     }, 
     topics:{ "$push": "$topics"} 
    }} 
]); 

所以,问题是,什么做youh觉得呢?你认为哪种模式是好的?

在此先感谢。

回答

0

更好的解决方案:使用参考来获得由用户发布

对于这个数据库的话题,人们通常需要考虑MMAPV1文件大小限制(16MB)。将用户,主题和注释放在一个文档中可以使文档无限制地增长。如果每个主题都是一个文本页面(1K),则每个用户在达到限制之前可以拥有约16,000个主题。这似乎很大,但如果您决定在产品成熟时将图像,视频和声音放在主题中,会发生什么?之后从嵌入式模式转换为规范化模式将比今天简单的设计选择做更多的工作。

同样,如果评论可能增长到导致主题超过16MB的限制,它们应该在一个单独的集合。不可能?大概。但是如果你写的东西会变成Huffington Post - 请查看他们热门文章的评论。

这是孟戈的建议data model design

+0

您好Steve,谢谢您的回答。 其实我们是在项目的开始,我仍然在设计数据库,所以不要担心转换数十亿的数据:) 我们计划使用亚马逊s3的文件,而不是将所有内容都存储在数据库中对于这个问题,它已经完成了。 例如,如果我使用规范化模式,我应该提出2个请求来检索主题+某些用户信息(名称,排名等),还是应该对主题中的用户信息进行一些重复? 谢谢 – user3550312

+0

使用两个find()s,一个用于用户集合,一个用于主题集合。为什么?想想如果在每个主题中都有相同信息的副本,您将如何更新用户信息。通过适当的索引,两次调用用户和主题都应该<1ms。 –

+0

事实上,我没有考虑更新信息......,我会研究一下mongo索引,因为我现在从未使用它。感谢您的意见。 – user3550312