首页 文章

MongoDB和Mongoose:文档引用ID的嵌套数组

提问于
浏览
1

我一直在深入研究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(更新帖子)和新的Comment,它们对于使用普通关系数据库时发送的请求都是通用的 . 当需要将新注释写入数据库时,会出现此问题 . 而不是像在普通关系数据库中那样进行一次数据库写操作,我必须进行2次写入和1次读取 . 第一次写入以插入新的Comment并检索_id . 然后通过Post _id检索发送请求的读取,以便我可以将新的Comment _id推送到嵌套的引用数组 . 最后,最后一次写入将Post更新回数据库 .

这似乎效率极低 . 我的问题是双重的:

  • 有没有更好/更有效的方法来处理这种关系模式(包含子引用ID数组的父级)?

  • 如果没有,使用此模式的好处是什么,而不是A)将父_id存储在子类的属性中,类似于传统的外键,或者B)利用MongoDB文档并存储注释数组而不是评论的参考ID数组 .

提前感谢您的见解!

1 回答

  • 3

    关于你的第一个问题:

    您特别要求更好的方法来处理存储在父级中的子ID . 如果它必须是这种模式,我很确定没有更好的方法来解决这个问题 .

    但是这个问题也存在于关系数据库中 . 如果要将帖子保存在关系数据库中(使用该模式),还必须先创建注释,获取其ID,然后更新帖子 . 当然,您可以在单个请求中发送所有这些任务,这可能比使用mongoose更有效,但需要完成的工作类型是相同的 .

    关于你的第二个问题:

    变体A的好处是,你可以获得帖子,并立即知道它有多少评论,而不要求mongodb通过可能的文件 .

    对于变体B的好处是,由于mongos 16MB文档大小限制,您可以在单个文档(单个帖子)中存储更多 references ,而不是 whole 注释 .


    然而,下行是您提到的那个,维持该结构是低效的 . 我认为,这只是展示场景的一个例子,所以这就是我要做的:我会根据具体情况决定使用什么 .

    • 如果文档将被大量阅读,并且没有多少写入, AND 它不可能大于16MB:嵌入子文档 . 这样,您就可以在单个查询中获取所有数据 .

    • 如果您需要从 multiple 其他文档 AND 引用该文档,您的数据必须一致,那么您别无选择,只能引用它 .

    • 如果需要从 multiple 引用该文档 BUT data-consitency不是那么超级重要 AND 来自第一个要点的限制适用,然后嵌入子文档,并编写代码以保持数据的一致性 .

    • 如果您需要从 multiple 其他文档中引用该文档,并且它们被写入很多,但不经常读取,那么您需要编写代码来同步重复数据 .

    在这个特定的情况下(帖子/评论)引用孩子的父母(让孩子知道父母 _id )可能是一个好主意,因为它确实知道文件不会超过16MB,嵌入它们会更好,因为以这种方式查询数据的速度更快

相关问题