MongoDB规范化与我的场景的非规范化

时间:2016-06-12 12:14:05

标签: mongodb

我们在NodeJS中重写后端后,将我们的应用程序移到了MongoDB。我唯一能够思考的事情就是我应该如何处理user-to-user消息的存储。我们的应用程序具有即时消息功能,使用相当多。

为了让您更好地了解,我们将采用以下方式查询数据。

.find(
    { message_to: new ObjectID("...") },
    { message_date: { $gte: timestamp } }
)

相当简单,获取自上次timestamp以来timestamp用户上次提取邮件的时间以来发送给用户的所有邮件。这样我们就只能请求新邮件。

我想弄清楚哪种方式可以更好地处理这类数据......

非规范化:

{
    participant_one: ObjectID("..."),
    participant_two: ObjectID("..."),
    messages: [
        {
            message_from: ObjectID("..."),
            message_to: ObjectID("..."),
            message_type: "TEXT",
            message_data: "Hello message",
            message_date: new Date()
        },
        {
            message_from: ObjectID("..."),
            message_to: ObjectID("..."),
            message_type: "TEXT",
            message_data: "Hello message",
            message_date: new Date()
        }
    ]
}

或者我应该做这样的事情......

{
    participant_one: ObjectID("..."),
    participant_two: ObjectID("..."),
    messages: [
        ObjectID("..."),
        ObjectID("..."),
        ObjectID("..."),
        ObjectID("..."),
        ObjectID("..."),
    ]
}

messages数组列出另一个收集此格式邮件的集合中的ObjectID:

{
    message_from: ObjectID("..."),
    message_to: ObjectID("..."),
    message_type: "TEXT",
    message_data: "Hello message",
    message_date: new Date()
}

请注意,user-to-user消息传递是我们应用程序中非常非常核心的功能,并且它经常被使用。目前,活跃用户之间的平均消息量为600 /会话。

1 个答案:

答案 0 :(得分:0)

如果绝大多数查询都是通过message_to和message_date进行的,我建议收集消息的第三种结构:

{
    participant_one: ObjectID("..."),
    participant_two: ObjectID("..."),
    message_from: ObjectID("..."),
    message_to: ObjectID("..."),
    message_type: "TEXT",
    message_data: "Hello message",
    message_date: new Date()
},

这实质上颠倒了你的关系,并使参与者从一个/两个从属于消息。优点是,使用此结构,您可以保持规范化,并且可以非常轻松地在所有消息属性上创建非常复杂的查询。

此外,使用mongo,很容易聚合结果,因此如果您需要与参与者关联的所有消息的数组(如上面的非规范化示例),则可以返回一个简单的查询或聚合(并且它将会如果在参与者字段上创建索引,也会很快。)

此外,从概念上讲,这种结构可以更好地模拟您的数据:消息是基本文档,所有其他字段都是属性(包括参与者等)。

如果您已经编写了一个应用程序(您提到您正在将预先存在的代码库转换为node.js),那么最好的办法是创建一个具有三种不同结构的测试数据库,然后运行应用程序的查询反对所有这三个,看看哪些用最简单的查询/代码给你最好的性能。