Q&答案网站的(MongoDB)数据库结构

时间:2013-08-18 11:43:28

标签: javascript node.js mongodb mongoose database

我试图建立一个类似雅虎的网站。答案或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,并检查它是否是用户自己,然后获取此用户名的所有对象匹配,这将是一个巨大的计算。我确信存在更好的方式,你们都有什么想法?

2 个答案:

答案 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'
    }