MongoDB和Mongoose:文档参考ID的嵌套数组



我一直在研究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
  }
});

这一切似乎都很好,花花公子,直到我开始从前端发送请求以创建新评论。该请求必须包含帖子_id(以更新帖子)和新注释,这都是人们在使用正常关系数据库时发送的请求所共有的。当需要将新评论写入数据库时,就会出现问题。我必须像在正常的关系数据库中一样写一个DB写作,而是要做2个写作和1读。第一个写作以插入新评论并检索_id。然后,读取以请求的帖子_id检索帖子,以便我可以将新注释_id推到嵌套的参考数组中。最后,最后一篇文章将帖子更新回数据库。

这似乎极低效率。我的问题是两个方面:

  1. 是否有一种更好/更有效的方法来处理这种关系模式(父母包含子参考ID数组)?

  2. 如果不是,使用这种模式的好处,而不是a)将父母_id存储在孩子的财产中,类似于传统的外键,b)利用mongodb文档和存储一系列评论,而不是评论的一系列参考ID。

事先感谢您的见解!

关于您的第一个问题:

您特别要求一种更好的方法与父母存储的儿童ID合作。我很确定,如果必须是这种模式,就没有更好的方法来处理。

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

关于您的第二个问题:

与变体A IS的好处,例如,您可以获取帖子,并立即知道它有多少评论,而无需要求MongoDB浏览可能的文档。

与变体B的好处是,您可以将更多的参考存储到单个文档(单个帖子)中,而不是全部注释,因为Mongos 16mb文档式限制。


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

  • 如果文档会被大量读取,并且写得不多,不太可能生长大于16MB:嵌入子文档。这样,您可以在一个查询中获取所有数据。

  • 如果您需要从>多个其他文档中引用文档您的数据确实必须是一致的,那么您别无选择,只能将其引用。<<<<<<<<<<<</p>

  • 如果您需要从>多个其他文档中引用文档,但是数据符号并不是超级重要的限制从第一个项目栏中应用,然后嵌入子插件,然后编写代码以保持数据一致。

  • 如果您需要从多个其他文档中引用文档,并且它们被写入很多,但不经常阅读,您可能会更好地参考它们,因为这样更容易编码,因为您不需要编写代码来同步重复数据。

在这种特定情况下(帖子/评论)从孩子中引用父母(让孩子知道父母_id)可能是一个好主意,因为它比相反的情况更容易维护,并且该文件可能会增长更大如果直接嵌入16MB,则比16MB。如果我肯定地知道,该文档不会大于16MB,嵌入它们会更好,因为它以这种方式查询数据的速度

最新更新