我想设计一个带有一些评论的问题结构。注释应该使用哪种关系:嵌入还是引用?

一个带有注释的问题,比如stackoverflow,会有这样的结构:

Question
    title = 'aaa'
    content = 'bbb'
    comments = ???

一开始,我想使用嵌入式注释(我认为MongoDB中推荐使用embed),像这样:

Question
    title = 'aaa'
    content = 'bbb'
    comments = [ { content = 'xxx', createdAt = 'yyy'}, 
                 { content = 'xxx', createdAt = 'yyy'}, 
                 { content = 'xxx', createdAt = 'yyy'} ]

这很清楚,但我担心这种情况:如果我想编辑一个指定的评论,我如何获得它的内容和它的问题?没有_id让我找到一个,也没有question_ref让我找到它的问题。(也许有一种方法可以做到这一点没有_id和question_ref?)

我必须使用ref而不是embed吗?然后我必须为评论创建一个新的集合吗?


当前回答

我知道这是相当古老的,但如果你正在寻找OP关于如何只返回指定注释的问题的答案,你可以像这样使用$(查询)操作符:

db.question.update({'comments.content': 'xxx'}, {'comments.$': true})

其他回答

好吧,我有点晚了,但仍然想分享我的模式创建方法。

我有可以用一个词描述的所有事物的模式,就像在经典的OOP中那样。

E.G.

评论 账户 用户 博客 ...

每个模式都可以保存为Document或Subdocument,因此我对每个模式都声明了这一点。

文档:

可以作为参考。(例如,用户做了一个评论->评论有一个“由”的参考用户) 是应用程序中的“根”。(例如,博客文章->有一个关于博客文章的页面)

子文档:

只能使用一次/绝不是参考。(例如,评论保存在博客文章中) 在应用程序中从来都不是“根”。(评论只在博客页面中显示,但页面仍然是关于博客的)

我知道这是相当古老的,但如果你正在寻找OP关于如何只返回指定注释的问题的答案,你可以像这样使用$(查询)操作符:

db.question.update({'comments.content': 'xxx'}, {'comments.$': true})

一般来说,如果实体之间有一对一或一对多的关系,则嵌入是很好的选择;如果实体之间有多对多的关系,则引用是很好的选择。

如果我想编辑一个指定的评论,如何获得它的内容和它的问题?

您可以通过子文档进行查询:Content ': 'xxx'})。

这将返回整个Question文档。要编辑指定的评论,您必须在客户端上找到该评论,进行编辑并将其保存回DB。

一般来说,如果您的文档包含一个对象数组,您会发现需要在客户端修改这些子对象。

实际上,我很好奇为什么没有人谈论UML规范。经验法则是,如果您有一个聚合,那么您应该使用引用。但如果它是一个组合,那么耦合更强,您应该使用嵌入式文档。

你很快就会明白为什么这是合乎逻辑的。如果一个对象可以独立于父对象而存在,那么即使父对象不存在,您也会希望访问它。因为不能将它嵌入到不存在的父节点中,所以必须让它活在自己的数据结构中。如果存在父对象,只需通过在父对象中添加对象的引用将它们链接在一起。

不知道这两种关系有什么区别? 下面是一个解释它们的链接: UML中的聚合与组合