Можно ли рассчитать скользящую среднюю / EMA / оконную совокупность по временному ряду в RavenDB 5 ?

#indexing #mapreduce #time-series #ravendb #moving-average

#индексирование #mapreduce #временные ряды #равендб #скользящая средняя

Вопрос:

RavenDB 5 добавляет поддержку хранения временных рядов для документов. В эту поддержку включена индексация, хотя для повышения производительности хранения и индексации индексация выполняется пакетами временных сегментов.

RavenDB включает поддержку вычисления базовых агрегатов Count / Avg / Sum для этих временных рядов в целом. Однако я не могу найти способ рассчитать скользящую среднюю по окну.

Например, у меня может быть 50 дней значений, по одному значению в день. Используя встроенный Avg, я могу тривиально индексировать среднее значение за все 50 дней. Тем не менее, я хотел бы создать поле индекса, которое содержит скользящую среднюю за окно, скажем, 5 дней. Поэтому значения первых дней X-1 будут нулевыми / пустыми, и с этого момента среднее значение будет рассчитываться за предыдущие X дней.

Я не могу найти тривиальный способ добиться этого в стратегии индексации карты / сокращения RavenDB, но я надеюсь, что мне не хватает какого-то умного способа (например) выполнить запрос из операции Map, чтобы запросить предыдущие значения, даже если они могут не попадать в текущий сегмент временных рядов.

Если это возможно, я также хотел бы иметь возможность пойти дальше и рассчитать соединение нескольких из этих скользящих средних — например, экспоненциальное скользящее среднее значения с течением времени.

Это идеальная операция для индекса, поскольку данные не изменяются после записи, но я не знаю, есть ли поддержка стиля окна / курсора при определении индекса RavenDB.

Я мог бы добиться этого, используя триггеры и т.д. в SQL-подобном хранилище вместо RavenDB, но, если возможно, я бы предпочел не прибегать к хранению некоторого кода в sprocs, а некоторого — в моей кодовой базе C #.

ТАЙЯ!

Комментарии:

1. Индексация временных рядов: ravendb.net/docs/article-page/5.1/csharp/document-extensions /… Запрос индекса: ravendb.net/docs/article-page/5.1/csharp/document-extensions /…

2. @Danielle спасибо, но это не проясняет, возможно ли создать индекс, содержащий значение, вычисленное по окну других (детерминированных) значений, например, в скользящем среднем

Ответ №1:

Не уверен, что есть более удобный способ, но индекс с уменьшением карты должен работать.

Карта:

 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
}
 

Уменьшить:

 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)
}
 

Комментарии:

1. Большое вам спасибо за ответ! Я не совсем понимаю, как я мог бы timeseries разрешить иметь Companies в качестве свойства (я на C # и наследую от AbstractTimeSeriesIndexCreationTask<T, TResult> ) — я использовал LoadDocument<T> для доступа к дочерним элементам. Но я с этим разберусь! Мой главный вопрос заключается в следующем: может ли эта операция отображения выходить за пределы границы сегмента временных рядов в RavenDB? Я думал, что это невозможно, но я буду рад ошибиться!

2. Вы можете попытаться определить этот индекс на live-test.ravendb.net с образцом данных. это соглашение об timeseries.Companies.StockPrices именовании, позволяющее указать индексу работать с данными временных рядов Companies коллекции, содержащей временные ряды StockPrices . Если вам нужно индексировать для каждой компании в отдельности, вы также должны сопоставить segment.DocumentId их и сократить по ним. Что вы имеете в виду segment boundary ? здесь индекс повторяется по каждой записи внутри сегмента ( from entry in segment.Entries )

3. Спасибо! Я попробую это сделать. Я читал это как Linq, а не как необработанное определение индекса. По границе сегмента я прочитал, что индексы временных рядов RavenDB вызывают Map только для сегмента временных рядов. Допустим, у меня есть данные за 1 год, и RavenDB разделил их на 500 сегментов. Будет ли этот метод корректно вычислять скользящую среднюю по всем данным, даже если временной интервал охватывает два временных сегмента? Может быть, я неправильно понимаю

4. Сегменты — это всего лишь деталь реализации того, как raven хранит данные временных рядов. Один сегмент может содержать около 2k-4k одномерных точек данных (точка данных == запись). В index сегменты отображаются для повышения производительности, вы можете получить доступ к Min / Max / Avg самого сегмента и в некоторых случаях избавить от необходимости перебирать записи в этом сегменте. Здесь следует упомянуть еще одну вещь: raven переиндексирует весь сегмент, если какая-либо из записей с этим сегментом изменилась. Надеюсь, это имеет смысл 🙂