【问题标题】:MongoDB equivalent of SQL greatest()MongoDB 相当于 SQL best()
【发布时间】:2013-11-26 11:45:44
【问题描述】:

我正在将底层数据库从关系数据库更改为 MongoDB,我需要通过 MongoDB 查询“重新创建”相同的语义。总而言之,这一切都很好,除了一件事:SQL best() 函数:

SELECT * FROM my_table
WHERE (GREATEST(FIELD_A, FIELD_B, FIELD_C, FIELD_D)
BETWEEN some_value AND some_value)
AND FIELD_E = another_value;

我似乎找不到这个 GREATEST() 函数的等价物。我知道可以通过使用 $cond 运算符来实现一些类似的功能,但是由于这里的 GREATEST() 函数正在寻找 4 个值中的最大值,这将是很多条件。有没有其他方法可以实现这一目标?我已经查看了聚合框架和 mapReduce,但我似乎无法在聚合框架中找到任何直接相似的东西,而且我很难理解 mapReduce 框架。

这甚至有可能实现吗?我会假设答案是肯定的,但我似乎真的找不到合理的等效方法。

【问题讨论】:

  • 需要注意的是greater不是SQL算子而是oracle算子,不是标准的
  • @Sammaye 你在这里绝对正确。然而,即使 best() 不是标准的一部分,关系型数据库也很普遍地支持它(oracle、mysql、postgresql、sqlite(尽管名称为 MAX))。
  • 两者并不完全相同,但是获得最大值的一种简单方法是在字段上对结果 DESC 进行排序
  • 您想要所有字段的事实使得聚合框架难以适应。特别是当您的查询并没有真正聚合时。 MapReduce 也会很麻烦。
  • MongoDb 的方式可能是在文档存储时预先计算“最大”值,而不是稍后在查询时。

标签: sql mongodb mongodb-java


【解决方案1】:

如果您查询引用的是您要复制的内容,您可以采取不同的路线...

您想要查找范围(加上其他条件)之间 4 个值中最大的所有文档。

您可以将其重新表述为所有 4 个值均低于上限且至少有一个高于下限的文档。 大致如下:

find(
    {field_a:{$lt:some_upper_limit}
    ,field_b:{$lt:some_upper_limit}
    ,field_c:{$lt:some_upper_limit}
    ,field_d:{$lt:some_upper_limit}
    ,$or:
        [{field_a:{$gt:some_lower_limit}}
        ,{field_b:{$gt:some_lower_limit}}
        ,{field_c:{$gt:some_lower_limit}}
        ,{field_d:{$gt:some_lower_limit}}
        ]
    })

看看索引如何帮助提高效率可能是个好主意,具体取决于数据等...

【讨论】:

  • 您不想将每个字段同时比较下层和上层吗?否则可能存在某种组合,其中一个字段满足一个条件,而另一个字段满足另一个条件?那么它在技术上与原始查询不同。
  • 条件状态不是关于单个字段(A、B、C 或 D)在界限之间。这是最伟大的。关键是标准是所有这些都必须低于上限(要求最大)并且任何都超过下限(这将包括在超过 1 的情况下的最大)。否则说,当且仅当所有值都低于上限并且任何值高于下限时,最大值才会在范围内......
【解决方案2】:

MongoDb 目前没有与GREATEST 等效的函数。您可以使用 MapReduce,但它不会提供有效的即时结果。此外,您将无法有效地返回文档的其他字段。您需要执行多个查询,或者可能复制所有数据。而且,如果不对结果运行更新过程,它就不会是最新的,因为文档被修改了,因为 MongoDb 中的 Map Reduce 必须手动启动。

MongoDb 聚合框架不适用于这种模式,如果可能的话,会导致非常冗长的管道。此外,它目前限制为 16MB 的结果,并且不会轻易返回超过您聚合的字段。返回select * 需要手动场投影,可能不止一次,具体取决于所需的输出。

鉴于您想要返回多个字段,并且结果不是聚合,我建议您做一些更简单的事情:

预先计算调用greatest 函数的结果,并将其作为新字段存储在文档中,以便在各种查询中轻松访问。

【讨论】:

  • 但您可以使用 MR 和 agg 框架并可能通过常规查找来做到这一点。
  • 当然,MR 可以工作,但这似乎不必要地复杂和低效。虽然人们可以通过一系列复杂的聚合步骤来做到这一点,尤其是在字段数量增加的情况下,但我也不推荐它。如果有任何要求返回整个文档而不仅仅是聚合,那么它们真的没有发挥 MongoDb 的优势(因为两者都旨在返回值和字段的聚合,而不是 select *。你不能这样做带有find。字段不能按照greatest 的要求进行交叉比较。
  • 请留下评论为什么你不投票。
猜你喜欢
  • 2011-07-11
  • 1970-01-01
  • 1970-01-01
  • 2012-05-04
  • 2014-03-19
  • 2015-05-26
  • 2018-09-18
  • 2020-02-13
  • 1970-01-01
相关资源
最近更新 更多