#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 переиндексирует весь сегмент, если какая-либо из записей с этим сегментом изменилась. Надеюсь, это имеет смысл 🙂