是否可以在 RavenDb 5+ 中计算时间序列的移动平均线/EMA/窗口聚合?

Ale*_*ffe 5 indexing mapreduce time-series moving-average ravendb

RavenDb 5+ 添加了对文档时间序列存储的支持。此支持中包括索引,尽管为了创建存储和索引性能优势,索引是按批次 TimeSeriesSegments 完成的。

RavenDb 支持计算这些 TimeSeries 上的基本 Count/Avg/Sum 总计。但是,我找不到计算移动的方法窗口内

例如,我可能有 50 天的值,每天一个值。使用内置的 Avg,我可以轻松地对所有 50 天的平均值进行索引。但是,我想创建一个索引字段,其中包含 5 天窗口内的移动平均值。因此,前 X-1 天的值将为空/空白,从该点开始将计算之前 X 天的平均值。

我无法在 RavenDb 的 map/reduce 索引策略中找到一种简单的方法来完成此任务,但我希望我错过了一些巧妙的方法(例如)从 Map 操作中运行查询以查询以前的值,即使它们可能不属于当前的 TimeSeriesSegment。

如果可能的话,我还希望能够更进一步并计算其中几个移动平均线的复合 - 例如,随时间变化的值的指数移动平均线。

这是索引的理想操作,因为数据写入后不会改变,但我不知道定义 RavenDb 索引时是否有窗口/游标样式支持。

我可以在类似 SQL 的存储中使用触发器等而不是 RavenDb 来实现此目的,但如果可能的话,我不希望将一些代码存储在存储过程中,而将一些代码存储在我的 C# 代码库中。

蒂亚!

Kar*_*ych 3

不确定是否有更好的方法,但映射减少索引应该可以工作。

地图:

from segment in timeseries.Companies.StockPrices
from entry in segment.Entries
let window = Enumerable.Range(0,5).Cast<object>()
from i in window
select new {
    Date = entry.Timestamp.AddDays((int)i),
    Value = entry.Values[0]*((double)1/(i+1)),
    Count = 1
}
Run Code Online (Sandbox Code Playgroud)

减少:

from r in results
group r by r.Date into g
select new 
{
    Date = g.Key,
    Value = g.Average(x=>x.Value),
    Count = g.Sum(x=>x.Count)
}
Run Code Online (Sandbox Code Playgroud)

  • 您可以尝试使用示例数据在 http://live-test.ravendb.net/ 上定义此索引。`timeseries.Companies.StockPrices` 是一种命名约定,用于告诉索引处理具有时间序列 `StockPrices` 的 `Companies` 集合的时间序列数据。如果您需要单独为每个公司建立索引,则可以应该映射`segment.DocumentId`并减少它。“段边界”是什么意思?这里索引正在迭代段内的每个条目(“来自段中的条目.Entries”) (2认同)
  • 段只是 raven 如何存储时间序列数据的实现细节。一个段可能包含大约 2k-4k 个单维数据点(数据点 == 条目)。在索引中,为了性能的考虑,段是公开的,您可以访问段本身的最小/最大/平均,并且在某些情况下无需迭代该段内的条目。这里要提到的另一件事是,如果该段的任何条目发生更改,raven 将重新索引整个段。希望这是有道理的:-) (2认同)