关于 MongoDB 具有一对多关系的数据建模的问题

Question about MongoDB data modelling with one-to-many relationship

我正在设计一个课程评论系统,我有评论文档,这些文档引用了用户对课程所做的评论。

我也有课程文档,但我在设计满足我需求的数据模型时遇到了问题。

课程和复习是一对多的关系。

我有两个选择:

  1. 在他们的评论对象中嵌入课程有很多:

在这种情况下,课程对象本身并不存在,但我必须允许我的用户搜索课程,因此在这种情况下,我需要 运行 查询 Review 对象以搜索课程。

  1. 如果我将课程存储在单独的集合中并通过 has_many 引用:评论

我还需要在用户搜索后点击课程时查找课程评论,使用这种设计,我将需要 运行 在检索课程评论时以及在我检索课程评论时进行查询我正在显示评论,我也需要显示课程,所以我需要 运行 另一个查询。

在这种情况下最好的设计是什么?我想我是否可以找到一种方法将课程作为一个单独的实体,并将其嵌入评论中。

编辑:我已决定按照建议在课程中嵌入评论,但我现在有一些新问题:

对于以下问题,请假设我在课程中嵌入了评论。

  1. 插入评论时,我应该在 ReviewController 中通过 id 找到它的课程并插入它的评论数组来完成吗?
  2. 当用户搜索课程时,我想 return 最后 10 条带有课程信息的评论而不是所有评论,因为这可能会减慢获取搜索结果的速度。如您所述,将所有评论都放入课程后,我如何才能实现这一目标?
  3. 我也有用户输入评论(又是一对多),我打算用用户名显示最近的评论,有没有办法在评论中只嵌入用户集合的用户名字段?
  4. 要找到特定的用户评论,我需要遍历所有课程,对吧?这不是一个很常见的查询,但有没有办法通过索引使其更快?

建模建议 - 课程有评论,评论由用户

I have decided to embed reviews inside courses as suggested but I have some new questions now:


  1. When inserting reviews, should I do it in ReviewController by finding its course by id and inserting inside its reviews array?

您正在更新课程集合文件。 update query filter will be by the course id (or name) - and you will $push ($push 是一个更新运算符)将复习子文档(或嵌入文档)放入课程文档的 reviews 数组 字段中。

course集合文档可以是这样的:

{
  _id: <ObjectId>,
  name: <string>,
  description: <string>,
  reviews: [
     { _id: <some id>, date: <date>, content: <string>, user: <...> },
     { _id: <some id>, date: <date>, content: <string>, user: <...> },
      ...
  ]
}

reviews子文档可以同时包含用户名和id其中之一


  1. When a user searches for a course, I would like to return last 10 reviews with the course information instead of all reviews because it may slow down fetching the search results. How can I achieve this after putting all reviews inside courses as you mentioned?

您可以将其设为聚合查询。例如,

db.course.aggregate([
  { $match: { _id: <some course id>  } },    // or, this can be filter by course name field
  { $addFields: {
       latestTenReviews: {
           // use $function aggregation operator to sort the reviews by the date field descending and 
           // limit to first ten array elements
       }
    },
])

$match阶段可以使用在_id上定义的索引(它默认有一个唯一索引)在课程上定义一个索引'的 name 字段。


  1. I also have users who enter the reviews (one to many again), I am planning to show recent reviews with usernames, is there a way to embed only username field of user collection inside review?

是的,您将用户信息存储在评论中,如前一点 (2) 所示。您可以只存储 id 名称 两者,具体取决于您的需要。当查询课程的评论时,如果存储了用户名,则会显示用户名。如果未存储姓名,您可能必须使用 $lookup 聚合阶段进行“加入”操作以获取用户详细信息,例如姓名。


  1. To find a certain users reviews I will need to iterate over all courses, right? It is not a very common query but is there a way to make it faster with an index?

您可以在reviews 数组字段的子文档的用户字段上定义索引。数组字段上的索引称为 Multikey indexes。以用户字段为过滤条件的查询将受益于该索引。