【问题标题】:Get nearest values outside of query range获取查询范围之外的最近值
【发布时间】:2014-03-01 13:39:34
【问题描述】:

我有一个 MongoDB 数据库来存储记录,这些记录具有创建时间的时间戳和值。我使用官方 C# 驱动程序连接并查询该数据库。

一个正常的用例涉及获取 >= startDateTime 和

但是,有时数据点距离周期的开始和结束足够远,我需要在 startDateTime 和 endDateTime 处插入值。为此,我显然需要 startDateTime 之前的最后一条记录,以及 endDateTime 之后的第一条记录。使用三个查询很容易做到这一点,但我想避免这种情况以减少到数据库的往返次数。

是否可以通过单个查询来实现?

编辑:因为我被要求澄清用例:

假设我有一个每小时记录一次温度的传感器。温度和时间戳存储在 MongoDB 集合中。现在,我想绘制昨天的温度图,所以我询问所有时间戳 >= 2014.02.04 00:00:00 且时间戳 的记录

事实证明,这个传感器每小时记录 55 分钟,所以我的第一个数据点是昨天的 55 分钟,而我的最后一个数据点是昨天结束的 5 分钟。

除了我的时间范围内的 24 个值之外,我还想获取 2014.02.03 23:55:00 和 2014.02.05 00:55:00 的值,以便进行插值。这需要概括为获取月经开始前的最后一条记录和月经结束后的第一条记录,因为我无法知道传感器记录的频率、记录时间或是否离线在任何时候。

Edit2:我现在的代码的缩写版本:

        //Get last record before the period
        var cursor = collection.Find(
            Query.LT("DateTime", startDateTime)
        );
        cursor.Limit = 1;
        cursor.SetSortOrder(SortBy.Descending("DateTime"));
        //Not shown: getting the record from the cursor and adding it to the collection

        //Getting all records that fall within the specified period
        cursor = collection.Find(
            Query.And(
                Query.GTE("DateTime", startDateTime),
                Query.LTE("DateTime", endDateTime))
        );
        //Not shown: getting the records from the cursor and adding them to the collection

        //Get first record after the period
        cursor = collection.Find(
            Query.GT("DateTime", endDateTime)
        );
        cursor.Limit = 1;
        cursor.SetSortOrder(SortBy.Ascending("DateTime"));
        //Not shown: getting the record from the cursor and adding it to the collection

【问题讨论】:

  • 我从未使用过 MongoDB。在 SQL Server 中,您可以使用几个 UNION 将这三个查询组合成一个。 MongoDB 是否支持 UNION 或等价物?
  • 是的,我也最熟悉 SQL。看起来可以使用 OR 运算符:stackoverflow.com/questions/14924129/…
  • 不确定我是否理解您的用例。您是说您正在尝试查找要在另一个查询中使用的开始日期和结束日期吗?如果您在问题中发布您实际在做什么的详细信息以进行澄清,这可能会有所帮助。
  • 我用一个例子更新了 OP,希望能阐明我在寻找什么。
  • 假设您有一个递增的 ID,简单的解决方案是获取该范围内的结果,然后在语法上,获取前面的一个和后面的一个 ...

标签: c# mongodb mongodb-.net-driver


【解决方案1】:

您的方法似乎是在寻找三个查询操作中隐含的 SQL UNION 的类似物。在这种方法中操作很清楚:

  1. 查找一天开始和一天结束范围内的所有记录
  2. 查找在日期范围开始之前出现的第一条记录
  3. 查找在日范围结束后出现的最后一条记录

虽然这很清楚,但可能只是我,但我没有看到这种方法的实用性。从您所写的内容来看,您似乎正在尝试为图表收集 24 个点,并且该图表将遵循 24 小时周期。因此,它会看到发出的三个查询的组合结果将返回最多 26 条记录和最坏 2 条记录之间。或者甚至可能有一个,如果事先没有记录并且取决于运行查询的时间。

鉴于此,有两条记录很可能超出您的一天范围,除了说在之前或之后的几个小时或几天内没有任何活动之外,没有多大用处。

我知道这是一个无代码响应,但没有 UNION 类似物可以执行您正在执行的操作,但我可以建议您可能不需要执行您正在执行的操作。

继续我所看到的和似乎是函数的内容,我看不出简单地获取少于一天结束 + 1 小时的记录并限制为最后 26 个(按降序排列)有什么问题。从那里您可以就要表示的数据做出任何您想要的决定,而且我们讨论的结果数量非常少。

如果您真的相信您必须拥有从您正在运行的查询中产生的一组结果,那么请务必运行这三个查询。同样,这些都是小的结果集,时间应该可以忽略不计。

【讨论】:

  • "这需要概括为获取月经开始前的最后一条记录和月经结束后的第一条记录,因为我无法知道传感器记录的频率,在哪个它记录的时间,或者它是否在任何时候离线。” - 也许我不清楚,但上述用例只是众多可能之一。很容易出现这样一种情况,传感器每秒记录一次,我需要查看半年的所有记录,并且恰好在该期间的开始期间发生为期一天的中断。这就是为什么我需要一个通用的解决方案。
【解决方案2】:

如果您不知道传感器记录的频率,以及是否真的有读数及时记录在“刚好在所需的 24 小时之外”,那么最好的方法是进行 3 次声明。

删除这两个约束之一可能会导致更少的语句。

如果您担心这 3 个请求“慢”,您应该努力使请求执行得更快,例如通过使用索引。

【讨论】:

    猜你喜欢
    • 2011-12-22
    • 1970-01-01
    • 2023-02-21
    • 1970-01-01
    • 2015-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多