在像StackOverflow这样的应用程序中(没有什么真正相关,但它是一个很好的例子),我们有Question
个。我们的mongodb集合中的每个Question
都有一个Answer
s数组,以及一个Vote
s数组(无论是upvoting还是downvoting)。
在每个Answer
中,User
可能会对其进行投票或投票。
因此架构看起来像这样:
Question
-> Answers []
-> Votes []
-> value (-1/1)
-> username
-> Votes []
-> value (-1/1)
-> username
-> question_text, etc.
来自MySQL背景,这种架构感觉“icky”,但我确信这是一种行业惯例。
现在我需要向每位用户展示他们投票的内容,包括Question
和Answer
。
因此,如果我必须找到用户投票的Answer
,我会查询(在节点中):
question_collection.find(
{'question.answers.votes.username': username}, function(e,d) {
/* do stuff */}
);
该查询深入4级。这是一种正常的方法,还是应该在模式中引入一些规范化?
答案 0 :(得分:1)
MongoDB的一个优点是,您可以将Question
的所有相关信息放在一个文档中,因此您只需要1个数据库查询而不需要连接来获取所有信息以呈现Question
但是,如果您想查找用户投票的所有内容,事情会变得复杂一些。当然,你可以做你做的事,虽然它不会赢得任何表现奖。
或者,您可以以更智能的方式复制数据,以便更轻松地访问它。例如,您可以向User
模型添加两个数组:
QuestionsVoted: [{ id1: +1}, {id2: -1}, {id3: +1}],
AnswersVoted: [{ id4: +1}, {id5: -1}]
这意味着您需要保持这些数据同步:当用户对问题或答案进行投票时,您需要更新问题和用户。这并不是那么糟糕,因为数据写得很少并经常阅读。
如果您有其他要求处理投票本身的要求,例如一段时间内投票的统计数据,或按地理区域,您可能需要创建一个Vote
集合。是的,您必须在3个集合中保持数据同步。
技术上可以在MongoDB中创建外键,但在这种情况下我不建议使用它。你会失去MongoDB的一些好处,因为它不擅长连接(它需要2个单独的查询)。
您可以阅读有关如何在MongoDB on their blog中设计关系的更多信息。