MongoDB、Mysql 和关系
Posted
技术标签:
【中文标题】MongoDB、Mysql 和关系【英文标题】:MongoDB, Mysql and relationships 【发布时间】:2012-05-04 09:11:06 【问题描述】:我正在创建一个在线聊天。
上下文(如果需要):
到目前为止,我一直在使用 php/mysql 和 AJAX 来完成这项工作,但这不是一个健康的解决方案,因为我坚持使用“拉”型应用程序,担心可伸缩性。 我阅读了有关“推送”方法替代方案的信息,看来我的选择是有限的并且排除了 PHP。 如果 Websockets 集成在每个浏览器中,它可能是一个非常有趣的选项,但事实并非如此(似乎对于大多数实现它的人来说,它默认是禁用的)。 长轮询也是一种候选方式,但它涉及其他问题,例如并发打开连接的数量也可能会杀死您的 Web 应用。
这就是为什么违背我的意愿,我认为我唯一可行的选择是使用服务器端 javascript(node.js + now.js 将是我的选择)。
这就是说,我可能也需要重新考虑数据库的使用。 我需要保留每个用户的存储数据并将这些用户链接到他们提交的消息。 如果是推送系统驱动的聊天引擎,那么 MySQL 是否仍然是一个有价值的选择? 我阅读了有关 NoSQL 数据管理的内容,似乎 MongoDB 将成为 node.js 的一个很好的补充。
我的两个问题:
对于实时 Web 应用程序,我是否有理由更好地迁移到 NoSQL 系统(我需要从头开始学习)而不是 MySQL(我已经知道)?
假设在 MySQL 中:
我有一个名为 user (user_id_p, username) 的表 我有一个名为 messages (message_id, message, user_id_f) 的表 我想进行一次查询以获取与用户名“omgtheykilledkenny”关联的所有消息。足够简单,但我如何通过 MongoDB 及其集合理念实现这一目标?
感谢您的帮助。
【问题讨论】:
#1:是的 - 速度和规模是两个原因 #2:使用 mongo 很容易做你想做的事情。您是否接受过 RTFM 并且有具体问题,或者您是要我们教您吗? 请相信我,我是 RTFM,但我就是不明白。我只是找不到如何在集合之间建立关系。对于有经验的开发人员来说这可能很明显,但对我来说没有意义。在同一个集合中进行简单查询是可以的,但是在两个集合之间组合数据以获得响应是我无法理解的。到目前为止没有找到任何与此相关的东西。除此之外,我相信我的问题非常具体。 【参考方案1】:使用 node.js/MongoDB 很酷,因为 Mongo 的文档结构已经是 JSONish,因此您不必将查询转换为 JSON。如果您已经了解 JavaScript,那么您将在学习 MongoDB 方面处于领先地位。 Mongo 确实可以轻松扩展写入和读取,速度非常棒,尽管我已经看到在单个系统上进行的一些 MySQL 基准测试与 Mongo 相当——当您开始需要多个盒子时,它真的很出色。
假设您有一个单独的消息集合,并且您已经知道您可以执行的用户 ID:db.messages.find(user_id:ObjectId(...));
更新:如果您不知道用户 ID,那么您需要执行两个查询,是的(除非您按照其他答案中的建议使用嵌入式数组——对于这种用例,我建议您不要这样做, 但是,因为您最终会查询整个文档/消息列表,甚至只显示一个子集)。根据您的用例,显然,如果您有用户名,您也可以方便地使用用户 ID,以应对这种情况。如果是客户端输入给出的用户名将不起作用。
更新 2:如果您有唯一的用户名,您可以将用户名设置为 users 集合的 _id 以避免此问题。大多数人可能会建议不要这样做,它有一些明显的缺点,例如更难更改用户名。
【讨论】:
谢谢韦斯·弗里曼。我的第一个答案是完全回答。对于第二个,我不确定。在您的示例中(我明确表示为 RTFM),它假定它将给我来自我提供的 user_id 的消息,但不会给我特定用户名的消息(在另一个名为“users”的集合中可用) .这很容易通过两个查询(我查询这个用户名的 id,然后我查询我检索到的用户 id 的消息)但是只有一个查询,我该怎么做呢?这就是我的观点。 谢谢。我想将您的两个答案都设置为有价值,但问题似乎只允许 1 个。关于此事,我不能在会话中保留任何 user_id,因为我可能需要任何用户的 id(或没有)。对于作为 id 的用户名,它不会回答我的问题,因为这里的用户名是一个示例。我需要它,但我还需要附加到消息中,用户性别、生日、头像等。这些是用户相关的,而不是消息相关的。用户数据和消息之间唯一的共同点是 user_id,因为我可能需要从消息中检索的用户数据比用户名更多。 是的,不幸的是,您需要执行两个单独的查询来获取所有用户属性和所有用户消息,或者将您的消息列表嵌入到用户中(这将难以扩展到许多消息)。 顺便说一句,进行两次查询并不是世界末日,除非您是一家银行进行交易,或类似的敏感信息。 我更喜欢查询两次而不是在消息集合中添加(非常)冗余信息。只是习惯于在 MySQL 中进行尽可能少的查询。我相信 dbrefs 是需要牢记的。如果它没有帮助,我会再做两个查询。【参考方案2】:您无法在 MongoDB 中执行连接,因此您无法实现第二个要求。 Mongo 这样做的方式是在用户集合中嵌套消息:
用户名:'abc',消息:[...]
或者使用 refId,它是连接和嵌套文档之间的一种中途之家:
http://uk3.php.net/manual/en/class.mongodbref.php
在从 MySQL 切换到 Mongo 方面,您不一定需要完全放弃 MySQL。在某些用例中,一个比另一个更合适。如果合适的话,您可以将两者用于系统的不同部分。就个人而言,我过去在很多事情上都使用过 MySQL,目前我正在将 MongoDB 用于一个大项目。我发现这个移动非常容易,因为使用 MongoDB 驱动程序非常容易,而且 MongoDB 站点总体上非常适合文档。
您可以使用前端的 json_encode 和 json_decode 与 JSON 进行转换,并使用 MongoDB 的 PHP 驱动程序查询和插入/更新数组,因此可以说它比 MySQL 更直观和更易于使用。只是习惯的问题。
【讨论】:
谢谢 Mick Sear,这很有趣。对于第一个问题,我阅读了很多关于每个系统的优缺点,但我只是不知道哪一个最适合我自己的用例。传统的“MongoDB 因为速度和规模”对我来说似乎太教条了。我不介意学习 MongoDB,但前提是它有意义。关于我的第二个问题,我似乎应该更多地了解 dbrefs。阅读 TFM 可能会向您展示查询语法,它不能帮助您应用理论概念。我仍然认为 MySQL 的方式,并尝试调整自己以适应不同的东西。没那么容易。 我愿意接受你的回答,但我只能接受一个。你的理论很有启发性。另一个更“直截了当”。谢谢你们。 @Baylock,你不能接受这个答案,但你可以随时投票 :) 很高兴我的回答对你有帮助!以上是关于MongoDB、Mysql 和关系的主要内容,如果未能解决你的问题,请参考以下文章