我应该如何在 mongodb / nosql 中存储数据?

Posted

技术标签:

【中文标题】我应该如何在 mongodb / nosql 中存储数据?【英文标题】:how should i store data in mongodb / nosql? 【发布时间】:2013-07-04 23:47:42 【问题描述】:

我正在 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
);

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

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

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

【问题讨论】:

为什么选择 MongoDB? 我阅读了很多关于数据库的信息并决定,MongoDB 最适合我的目标(node.js+socket.io+express)。我应该用什么代替你的意见? :) 我不确定 MongoDB 是否适合“社交”网络类型的消息传递系统。低容量,它可以工作,但对于高容量,没有连接的事实可能会使数据整理从性能角度来看具有挑战性,没有大量缓存等。在任何代码之前需要完成大量设计是写的。 :) 你会推荐什么数据库而不是 MongoDB? mysql?无论如何,我在 MongoDB 上写了很多,并读到 MongoDB 疯了,每个人都应该使用它) 你可以使用你想要的,我不想推荐一个没有更多细节的特定平台(而且 *** 不是这类讨论的好地方)。 【参考方案1】:

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

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

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

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

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

【讨论】:

感谢您的回答。简而言之,我该怎么做?选择第二种方式将消息存储在数据库中? @sirjay 这取决于您如何使用数据库。面向文档的数据库like we have for relational databases 没有“一种正确的方法”(或者可能有一种方法,但我们还没有弄清楚)。找出最常见的查询并针对这些查询进行优化。

以上是关于我应该如何在 mongodb / nosql 中存储数据?的主要内容,如果未能解决你的问题,请参考以下文章

开发者如何学好 MongoDB

MongoDB电子商务网站的数据建模

NoSQL 的用例 [关闭]

我们如何确保 mongoDb 中的数据完整性?

NoSQL(MongoDB)与Lucene(或Solr)作为您的数据库[关闭]

如何在noSQL中选择所有名称中的状态(MongoDB)