3

我正在 node.js 和 mongodb(mongoose 模块)上编写一个大型社交网络。这意味着数据库中会有很多用户和大量数据。

我已经创建了用户注册,现在我需要允许用户互相写私人消息。

问题:

1)我应该如何存储有关发送私人消息的数据?我想了两种方法:

第一的

var schemaUser = new mongoose.Schema({
    i: Number,
    ...
    message: { type: Schema.ObjectId, ref: 'Message' }
});
var schemaMessage = new mongoose.Schema({
    m: [{
        f: Number, // value i from schemaUser, means from user
        m: String, // message
        d: { type: Date, default: Date.now } // date
    }]
});
module.exports = {
    User: db.model('User', schemaUser),
    Message: db.model('Message', schemaMessage)
}

这样,每个用户都有message字段到Message表,他只有一个集合m,其中数组存储所有消息。

第二

我存储在这样的Messages所有消息中:

var schemaMessage = new mongoose.Schema({
    t: Number, // means to what user this messages sent
    f: Number, // value i from schemaUser, means from what user message sent
    m: String, // message
    d: { type: Date, default: Date.now } // date
});

所有消息都混合在一个表中。但据我了解,这种方法的缺点是数据库中可能有超过一百万条私人消息,这就是为什么查找from用户和to用户发送的消息的速度和性能会很差。当使用一种方法时,所有消息都在数组中。

那么,我应该选择哪种方式或任何其他想法?

2)我有第一种方法的数组:var arr = [] 问题:我可以放入多少个对象arr?大小是arr多少?例如,如果我推动类似的东西arr.push({t: #, f: #, m: 'message...'})

4

1 回答 1

7

一般来说,MongoDB 鼓励嵌入数据而不是关系,因为这允许通过单个查询获取所有相关数据。但是,有一个例外:MongoDB 不喜欢无限增长的文档。

当文档在其生命周期内逐渐增长时,数据库必须频繁地重新分配硬盘空间。这会减慢写入速度并导致数据库碎片。此外,文档的硬编码大小限制为 16MB(主要是为了阻止文档增长)。用户在其会员资格期间积累越来越多的私人消息将是无限增长的一个很好的例子。

在您的情况下,确定最常见的用例很重要。您将如何向用户显示私人消息?他们会在一个长长的 HTML 页面上看到他们曾经收到的所有消息及其全文吗?不太可能。

您可能希望将它们列为带有发件人和标题的电子邮件收件箱,并在用户单击它们时显示实际内容。在这种情况下,您应该只存储一个包含此元数据的数组,并将实际内容存储在不同的集合中,当用户实际单击消息时会查询该集合。这样你仍然有增长,但这不会成为问题,因为存储在用户文档中的每条消息的数据要少得多。

您也可能只想在每个普通页面展示中显示那些未读的消息,而旧私人消息的完整列表是一个使用频率较低的特殊页面。在这种情况下,您只需将未读消息嵌入到用户文档中,并在阅读后将它们移动到另一个集合中。这可以防止文档增长,因为大多数用户会将未读消息列表保持在较低水平。

于 2013-07-08T14:10:12.273 回答