这个 Mongo 查询和这个 SQL 查询一样吗?我是不是正确地考虑了Mongo?

Posted

技术标签:

【中文标题】这个 Mongo 查询和这个 SQL 查询一样吗?我是不是正确地考虑了Mongo?【英文标题】:Is this Mongo query the same as this SQL query? Am I thinking about Mongo correctly?这个 Mongo 查询和这个 SQL 查询一样吗?我是否正确地考虑了Mongo? 【发布时间】:2014-05-07 12:06:35 【问题描述】:

这并不是负面的,因为我一直在阅读 Mongo 文档。我对这个概念很陌生。 Mongo 被吹捧为这个正在扼杀 mysql 的超高效数据库,但我读到的所有 Mongo 语句似乎都可以简化为,因此没有更高效的 SQL。也许我采取了错误的方法。

假设您有两个表:

User

ID    Name    FavoriteColor
1     John    1
2     Jona    2
3     Jack    1

Color

ID    Name
1     Red
2     Green
3     Blue

为了获得用户的颜色,我会这样做

SELECT
  `u`.`Name`,
  `c`.`color`
FROM `user` AS `u`
LEFT JOIN `color` AS `c` ON `u`.`FavoriteColor` = `c`.`id`

不确定该语法是否正确,我面前没有 MySQL。

现在 Mongo 不支持连接(人们说这是 Mongo 的重点)所以如果我要这样做,我会迭代用户集合,然后对于每条记录,我会根据该用户最喜欢的颜色 ID 查询颜色数据库和“迭代”颜色集合(应该只返回一行)。但这似乎与(在 php 中)完全相同:

<?
        $query = "SELECT `Name`, `FavoriteColor` FROM `users`";
        $result = mysql_query($query);
        while($row = mysql_fetch_array($result)) 
             $username = $row["Name"];
             $query = "SELECT `Name` FROM `Color` WHERE `id` = " . $row["FavoriteColor"] . " LIMIT 1";
             $result = mysql_query($query);
             $color = "";
             //I know we return only one row but I am illustrating the concept of scanning the entire color table
             while($row2 = mysql_fetch_array($result)) 
                  $color = $row2["Name"];
             

             echo "Hi I'm $username and my favorite color is $color <br>";
        
?>

从效率的角度来看,我看不出 MongoDB 如何比 SQL 更快(join 或 php 迭代方式似乎仍然是同一件事)。归根结底,它必须扫描整个用户表,并且对于每个用户,它必须扫描整个颜色表以将 colorID 与最喜欢的颜色匹配。

我应该尝试从逻辑上减少 MongoDB 存储到行\列\表中,还是 MongoDB 本身的执行方式不同?

【问题讨论】:

这是一个非常好的问题,来自我的 +1。现在我只需要等待 Mongo ***者在不自掘坟墓的情况下尝试解释这一点 :) 【参考方案1】:

您对 MongoDb 中缺乏加入支持是正确的。它允许 MongoDB 集合自动分布,而不会被要求在两个分布式集合(表)之间加入。如果可能的话,这将导致在服务器上进行大量工作,并且根本无法扩展。

所以它不支持连接,但它是面向文档的数据库,它支持嵌入文档。它极大地影响了数据库结构设计。现在您可以选择是嵌入还是创建新的集合(表),具体选择取决于数据本身和数据使用模式,因此您需要提前了解您的数据使用模式。 回到您的示例,这两个表可能会合并到一个集合中user,您可能会有这样的事情:


  name: John,
  favoriteColor: Red

在这种情况下,检索相同数据不需要连接。是完全不同的结构设计。但是,MongoDB 不支持约束(唯一性除外),您需要注意不要尝试使用不存在的颜色。为此,您可以有单独的 color 集合,并在将数据插入集合 user 时检查数据。

总结: MongoDB 的效率不在于更快地执行相同的操作,而在于能够使用不同的范式对旧问题进行建模。

【讨论】:

我也可以在 SQL 用户表中添加“红色”,但有时人们有两个表,因为假设红色、绿色和蓝色是唯一可用的颜色。我为他们准备了一个单独的表格,这样我就可以查询该表格来填充下拉列表或其他内容。在 MongoLand 中,您会按照您的描述进行操作,然后单独收集可用颜色吗? 如果您需要约束值,您仍然可以在 MongoDB 中单独收集颜色。这里没有黑魔法。您也可以将 Red 放入 SQL 用户表中(尽管它会破坏规范化)。但是让我们超越那个简单的例子,想象用户可以有多种不同的颜色,也可以有一些偏好,也可以有一些设置。在 MongoDb 中,您可以将所有这些内容放在一个文档中,并提供丰富的查询选项,此外,是否可以通过副本集具有持久性并通过分片进行分发。【参考方案2】:

为了能够理解 MongoDb,您需要尝试抛开您在 RDBMS 中所学的知识。

MongoDB 是一个“动态模式”系统,是一个基于文档的数据库,围绕对象概念的数据。

在您发布的示例中,您使用的结构仍在为您的设计实现更多的关系数据库方法。为了扩展复杂数据和开发速度,并记住没有加入支持,我建议您重新审视您的设计并“去规范化”您的集合,即使您认为它可能看起来多余(基于如何数据库已经设计了 40 年)

【讨论】:

【参考方案3】:

首先,Mongo 可能正在杀死 MYSQL,但它甚至还没有接近 MYSQL。

User

ID    Name    FavoriteColor
1     John    RED
2     Jona    GREEN
3     Jack    RED

这就是您的数据在 mongo 中的外观。 Mongo 不支持连接,但支持嵌入式文档。如果您要经常查询该数据,则始终建议您将数据放入 mongo 中的单个集合中。简而言之,将没有颜色表/集合。最有可能的是,获取用户和颜色的查询是

db.collection.find(,name:1,favoriteColor:1)

您的收藏文档将如下所示。


  id: 1
  name: John
  FavCol: RED

【讨论】:

你知道这根本没有回答问题吗? 我不会尝试向您解释这个问题,但您基本上重复了OP在他的帖子中提到的内容。把这个作为答案是愚蠢的。 @N.B.我也不需要你的解释,你最好读 10 到 15 遍,也许你会有所了解:) 无论如何谢谢。 看来这里的语言障碍太大了,我就让你和隐形敌人和紫色独角兽展开你的网络战争。

以上是关于这个 Mongo 查询和这个 SQL 查询一样吗?我是不是正确地考虑了Mongo?的主要内容,如果未能解决你的问题,请参考以下文章

将Mongo查询转换为spring Mongooperations

怎样将数组作为sql中in的查询条件?

SQL 和 Mongo 等效查询

es 条件查询能像数据库那样灵活吗?

我可以重写这个 SQL 查询以避免“ORDER BY 子句无效”吗

node查询mongo