我试图建立一个类似雅虎的网站。答案或StackOverflow(不同的类别,没有竞争),而且我在这一点上陷入困境,我非常感谢你们的任何指导,因为我对MongoDB很新。
我顺便在Node.js和MongoDB上使用Express框架。
问题是找到为用户和问题/答案数据构建数据库的最有效方法。
目前,有一个问题模型,其中包含每个类别的文档。每个文档都包含问题本身,答案和其他信息,如下所述:
math{
OpenQuestions{
'x+2=5, whats x?' : {
asker: 'peter',
likes: 12,
answers: {
'x is 3' : {
answerer: 'john',
likes: 25
},
'x is 2' : {
answerer: 'MATHSUX',
likes: 0
}
}
}
}
ClosedQuestions{
//same as OpenQuestions
}
}
通过这种方式,我们可以很容易地显示问题,因为我们可以根据对象的创建时间轻松检索问题,并在主要问题页面上相应地获取问题。
但是,如果用户想要查看他提出的问题,我能想到的唯一方法是查看每个subject.OpenQuestions.QuestionItSelf.asker
,并检查它是否是用户自己,然后获取此用户名的所有对象匹配,这将是一个巨大的计算。我确信存在更好的方式,你们都有什么想法?
答案 0 :(得分:1)
MongoDB每个文档的限制为16MB。此外,如果文档的大小增加,MongoDB的表现也不会很好。出于性能原因,MongoDB尝试将文档保存在硬盘驱动器的连续部分中,因此当文档增长时,需要不断重新分配硬盘空间。
由于这些原因,将所有问题存储在单个文档中并不是一个好主意。
最好创建一组问题,并为每个问题单独提供一个文档。要提高搜索效果,您可以创建一些合适的indices。
顺便说一句:我不确定MongoDB是否适合您的项目。您的应用程序听起来非常关系,并不像它可以受益于MongoDB的面向文档的概念。另一方面,您的分层思维方式听起来更符合Redis哲学。但这只是一种主观意见。
答案 1 :(得分:1)
首先,将问题作为关键是一个坏主意。创建一个question
属性,并将该属性的值作为问题的文本。 MongoDB没有太多的工具来查询键值。几乎所有的都是$exists
,甚至不支持通配符。对每个答案执行相同的操作,而不是将答案的文本作为键,使用answer
键并将值作为答案的文本。
接下来,没有理由将所有问题保留为子文档。您可以将状态移动到文档的属性(状态:'打开'或状态:'关闭'或状态:'已解答但未关闭',例如)。如果您需要预先计算状态 - 将答案作为子文档更有意义,然后您可以根据答案的状态派生状态(即,如果问题没有任何答案然后它显示为未答复,如果它有答案但没有被标记为解决方案然后它的答案但没有解决,如果它的答案标记为解决方案然后它已关闭等等。)
然后,让主题成为问题的属性,而不是每个主题的集合。如果你这样做,那么为提问者找问题就像
一样简单db.questions.find({asker: 'John'}, {question:1, _id:0})
这将显示John提出的所有问题的文本
您的最终架构将是一个问题集合,其文档结构如下所示:
{
question: 'x+2=5, whats x?'
asker: 'peter',
likes: 12,
subject: 'math',
answers: [
{ answer: 'x is 3', answerer: 'john', likes: 25, solution: true },
{ answer: 'x is 2', answerer: 'MATHSUX', likes: 0}
],
status: 'solved'
}