【发布时间】:2017-03-19 07:31:28
【问题描述】:
我一直在深入研究 MongoDB,并遇到了一种特别有趣的模式来存储文档之间的关系。此模式涉及包含引用子文档的 id 数组的父文档,如下所示:
//Parent Schema
export interface Post extends mongoose.Document {
content: string;
dateCreated: string;
comments: Comment[];
}
let postSchema = new mongoose.Schema({
content: {
type: String,
required: true
},
dateCreated: {
type: String,
required: true
},
comments: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Comment' }] //nested array of child reference ids
});
以及被引用的孩子:
//Child Schema
export interface Comment extends mongoose.Document {
content: string;
dateCreated: string;
}
let commentSchema = new mongoose.Schema({
content: {
type: String,
required: true
},
dateCreated: {
type: String,
required: true
}
});
在我从前端发送请求以创建新评论之前,这一切看起来都很好。请求必须包含 Post _id(用于更新帖子)和新评论,这对于使用普通关系数据库时发送的请求都是常见的。将新评论写入数据库时会出现此问题。我必须执行 2 次写入和 1 次读取,而不是像在普通关系数据库中那样执行一次 db 写入。第一次写入以插入新评论并检索 _id。然后读取通过随请求发送的 Post _id 检索 Post,以便我可以将新的 Comment _id 推送到嵌套引用数组。最后,将 Post 更新回数据库的最后一次写入。
这似乎效率极低。我的问题有两个:
是否有更好/更有效的方式来处理这种关系模式(父级包含一组子引用 ID)?
如果不是,与 A) 将父 _id 存储在与传统外键类似的子属性中,或 B) 利用 MongoDB 文档并存储Comments 数组,而不是 Comments 的引用 id 数组。
提前感谢您的洞察力!
【问题讨论】:
-
不要将 cmets 引用为帖子中的列表,只需在帖子的评论中使用一个引用即可。您需要它的帖子 ID,并且只写一次。检索与一个帖子相关的所有 cmets。
-
@Myonara,感谢您的反馈,非常感谢。但是,我的问题更具体地说是一个架构问题,即为什么人们会选择这种模式而不是你提到的模式,以及是否有更好的方法来实现所讨论的第一个模式。
-
这里是 CMS 风格用例 docs.mongodb.com/ecosystem/use-cases/storing-comments 的一篇文章。这谈到了选项 B。希望它有助于为您澄清一些事情。
标签: javascript node.js mongodb mongoose relationship