制作博客;无法决定使用MongoDB还是MySQL

6

好的,我将为我的网站使用Node.js编写博客(作为学习过程),并且一直在激烈地争论应该使用MySQL还是MongoDB。

搜索了一些“如何在Mongo中编写博客”的指南,但它们似乎没有涵盖我遇到问题的类型。这是我的困境:

如果我使用MySQL,我想象我的模式大致如下:

帖子:

ID, USER, DATE, TITLE, TAGS

评论:

POST_ID, USER, DATE, MESSAGE

用户:

ID, SCREEN_NAME, IMAGE_URL

所以,每篇文章都有相关的评论,每个帖子和评论都有相关的用户。优点是,如果用户想要更改他们的屏幕名称或图像,只需要更新用户表中的一行。但是,我不确定如何获取包含X标签的所有帖子,除非我为多个潜在标签使用多个字段?
另外,使用类似于MongoDB的东西,我正在考虑将其格式化为以下方式:
帖子收集:
{ 
    {
    _ID: something
    USER: {id: id, name: "screen name", image: "image_url"}
    DATE: ...
    TITLE: ...
    TAGS: [tag1, tag2...]
    COMMENTS: 
         [
         {USER:someone, DATE:something, MESSAGE:"hi"},
         {USER:someone, DATE:something, MESSAGE:"another message"}
         ]
    },
    {
    _ID: something,
    USER: {id: id, name: "screen name", image: "image_url"},
    DATE: ...
    TITLE: ...
    TAGS: [tag1, tag2...]
    COMMENTS: 
         [
         ...
         ]
    },
}

因此,每个帖子中嵌入了评论,这似乎很自然。
在这里,一个查询可以检索与之匹配的所有帖子,这非常棒。另一方面,如果我需要更新用户使用的屏幕名称或图像,则似乎很难挖掘给定文档中嵌入的对象,更不用说更新跨每篇文章的所有相关记录了。
我可以将评论移动到单独的集合中以使它们更易于访问,但我仍然需要针对诸如屏幕名称之类的内容进行大量更新。
因此...
基本上,我更喜欢使用MongoDB,因为它可以轻松地完成各种操作,并且使用同一语言工作很好。然而,我不禁觉得我需要采用关系型方法才能“正确”地完成任务。
有没有人在任一或两种语言中做过类似的事情?
您对此有何看法,特别是如何处理用户和评论/帖子之间的关系?
感谢您的帮助 :) 詹姆斯

使用Disqus进行评论,使用Jekyll进行部署 - 仅需10分钟即可拥有完全可维护的设置。 - moonwave99
3个回答

7
这个问题与性能无关,因为MongoDB和SQL都会以相同的方式选择这样一个小数据集,所以没有真正可测量的性能提升。
在这种情况下,MongoDB的主要优点是能够将许多表嵌套在一个表中,从而减少更新信息时需要查询的次数。例如,您只需查询一个表,而不是12个表。此外,有时模式可以更自然地反映您实际使用数据的方式。
我会在您的模式中做出一些改变:
USER: {id: id, name: "screen name", image: "image_url"}

这应该只是一个ObjectId,与用户行相关,并再次在注释中出现:

{USER:someone, DATE:something, MESSAGE:"hi"}

使用ObjectId作为USER字段的值。这些ObjectId将与用户集合相关联。同时删除那些大写字母,因为我感觉在编码时会很麻烦。
至于处理关系:将可重复信息嵌套到实体中作为子文档(这通常应该在第一范式中进行规范化),但这并不意味着你应该无限嵌套,通常建议最多嵌套3层以保证查询兼容性,并考虑应用程序实体的边界,如blogpostuser
现在你需要处理非嵌套关系,例如bloguser行(因为帖子将有嵌套的评论等)。解决这些关系的方法是在客户端处理,因为MongoDB没有关系理念(它是一个RDB异教徒)。
你只需像MySQL通常在服务器端那样,在客户端选择单独选择用户,然后基于该用户ID选择帖子,而不是选择每个行都是用户和帖子表之间连接的巨大结果集。

嗨,大写字母只是为了演示目的,以保持与我编写的mySQL部分一致 :)至于用户行; 那很有趣。我故意嵌入了用户数据,以便减少查询; 在其他地方拥有用户数据意味着查询以检索每个评论的用户的图像/名称,这对我来说不正确。 - jsdw
@lytnus 嵌入此信息的问题在于更新方式。想象一下,如果用户想要更改他们的用户名,这意味着您需要遍历所有帖子和/或评论并更新该用户的用户名,这非常不可扩展。在这种情况下,用户行应该是单独的。因此,这是考虑某些内容是否应该嵌入的另一种方式,因为它是否仅关注于该项,例如评论仅关注于帖子。 - Sammaye
谢谢。我认为我的主要担忧是我需要进行的查询量。我想这是一个权衡;每次查看评论时,您可以进行大量查询,但只需进行一次查询即可更新用户信息,或者进行大量查询以更新用户信息,但只需进行一次查询即可读取评论。如果经常阅读评论,我可以看到倾向于嵌入式方法是值得的。无论哪种方式,我的思维现在很放松,我将选择MongoDB :) - jsdw
@lytnus 是的,MongoDB也是为读取密集型场景设计的,因此查询数量并不重要,这是在进行NoSQL时抛弃SQL规则书的情况。实际上,游标本身直接从数据库流式传输,而不像SQL从写入内存或磁盘的特定结果集中读取。因此,每次通过游标从数据库获取新行时,实际上都会再次在数据库上运行该查询。 - Sammaye
太棒了,感谢提供这么有用的信息!而且它更容易上手和使用,所以我被吸引了! - jsdw

0

我不同意需要采用关系型方法才能正确地完成事情。

决策取决于您是否可以放弃ACID和关系上的细节。

如果您的博客是基于文档的,也许NoSQL方法会很好地工作。

更好的方法是,您可以在接口后面抽象出如何持久化事物的细节,并在使用Java或C#等面向对象语言时将一个实现替换为另一个实现。您不需要以这种方式被锁定。


我想我的问题实际上是,如果你放弃关系型数据库的优雅性,你如何处理用户和帖子之间的关系,以便像更新用户屏幕名称等操作可以高效地完成? - jsdw
NoSQL 倾向于更多地基于文档。如果您的用例不适合这种方法,那么您的决定就已经做出了。 - duffymo
如果你需要创建一个与我的类似要求的博客(非常基本的博客),你会采用关系数据库还是NoSQL的方法?对于你而言,当一个用户更改他们的屏幕名称时,必须更新很多东西的缺点是否超过了NoSQL方法带来的更快的基于文档的访问的好处?你的模式与上面的模式是否不同? - jsdw
1
我不知道使用NoSQL访问文档是否更快,你也不知道。如果你将每个博客条目存储为关系数据库中的CLOB(Character Large Object),与NoSQL并没有太大区别。 - duffymo
@lytnus 直到你处理超大型数据集时,才会真正感受到性能差异。当获取小型博客时,MySQL 和 NoSQL 的速度相同,因为它们都以相同的方式获取。这就是为什么这个问题没有一个确切答案,因为它取决于你的偏好,这太主观了。 - Sammaye
是的,你说得对。我确信。即使我意识到对于我自己的目的来说,我很可能永远不需要担心它,但我仍然喜欢从一开始就考虑可扩展性。感谢您的评论。 - jsdw

-7

我会建议使用 WordPress,它非常流行,而且我从未在使用中遇到过性能问题!今天全世界25%的网站都在使用 WordPress!


1
我同意WordPress是一个不错的选择,但我正在使用Node.js(而非PHP)进行学习练习,所以这并不适用于我。 - jsdw
2
什么好的解决方案?你在评论之前甚至都没有读他发布的问题。无关主题的回复。 - Sanjay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接