Indexing: Time Series
Time series indexes process time series segments,
rather than document fields.
The API for creating time series indexes is very similar to (and it inherits
from) the API for creating document indexes.
Syntax
There are two main ways to create a time series index:
-
Create a class that inherits from one of the abstract index creation task classes:
AbstractTimeSeriesIndexCreationTask
for map and map-reduce time series indexes.AbstractMultiMapTimeSeriesIndexCreationTask
for multi-map time series indexes.AbstractJavaScriptTimeSeriesIndexCreationTask
for static javascript indexes.
-
Create a
TimeSeriesIndexDefinition
.
AbstractTimeSeriesIndexCreationTask
public abstract class AbstractTimeSeriesIndexCreationTask :
AbstractIndexCreationTaskBase<TimeSeriesIndexDefinition>
{
protected void AddMap(string timeSeries,
Expression<Func<IEnumerable<TimeSeriesSegment>,
IEnumerable>> map);
protected void AddMapForAll(Expression<Func<IEnumerable<TimeSeriesSegment>,
IEnumerable>> map);
}
// Index only time series that belong to documents
// of a specified type
public class AbstractTimeSeriesIndexCreationTask<TDocument> { }
// Specify both a document type and a reduce type
public class AbstractTimeSeriesIndexCreationTask<TDocument, TReduceResult> { }
Method | Parameters | Description |
---|---|---|
AddMap() |
string timeseries , Expression map |
Sets a map function for all time series in the database with specified name (the first parameter) |
AddMapForAll() |
Expression map |
Sets a map function for all time series in the database |
See the example below.
AbstractMultiMapTimeSeriesIndexCreationTask
public abstract class AbstractMultiMapTimeSeriesIndexCreationTask
{
protected void AddMap<TSource>(string timeSeries,
Expression<Func<IEnumerable<TimeSeriesSegment>,
IEnumerable>> map);
protected void AddMapForAll<TBase>(
Expression<Func<IEnumerable<TimeSeriesSegment>,
IEnumerable>> map);
}
// Specify a type for the reduce result
public abstract class AbstractMultiMapTimeSeriesIndexCreationTask<TReduceResult> { }
Method | Parameters | Description |
---|---|---|
AddMap<TSource>() |
string timeseries , Expression map |
Sets a map function for all time series with the specified name (the first parameter) that belong to documents with the type TSource |
AddMapForAll<TBase>() |
Expression map |
Sets a map function for all time series that belong to documents with either the type TBase or any type that inherits from TBase |
See the example below.
AbstractJavaScriptTimeSeriesIndexCreationTask
public abstract class AbstractJavaScriptTimeSeriesIndexCreationTask : AbstractTimeSeriesIndexCreationTask
{
public HashSet<string> Maps;
protected string Reduce;
}
Property | Type | Description |
---|---|---|
Maps |
HashSet<string> |
The set of javascript map functions |
Reduce |
string |
The javascript reduce function |
See the example below.
Learn more about JavaScript indexes.
TimeSeriesIndexDefinition
public class TimeSeriesIndexDefinition : IndexDefinition
For now, TimeSeriesIndexDefinition
is functionally equivalent to the
normal IndexDefinition
.
Using it for time series indexes is recommended - it exists in case additional functionality is
added in future versions of RavenDB.
See the example below.
TimeSeriesSegment Object
Time series entries are indexes through the segment they are stored in, using LINQ syntax that resembles this one:
from segment in timeseries
from entry in segment
Segment properties include the entries data, and the aggregated values that RavenDB automatically updates in the segment's header.
Property | Type | Description |
---|---|---|
DocumentId | string | The ID of the document this time series belongs to |
Name | string | The name of the time series this segment belongs to |
Min | double[] | The smallest values from all entries in the segment. The places in this array correspond to the |
Max | double[] | The largest values from all entries in the segment |
Sum | double[] | The sums of values from all entries in the segment. The first Sum is the sum of all first values, and so on. |
Count | int | The number of entries in this segment |
Start | DateTime | The timestamp of the first entry in the segment |
End | DateTime | The timestamp of the last entry in the segment |
Entries | TimeSeriesEntry[] |
The segment's entries themselves |
These are the properties of a TimeSeriesEntry
, which are exposed in the LINQ syntax:
public class TimeSeriesEntry
{
public DateTime Timestamp;
public string Tag;
public double[] Values;
// This is exactly equivalent to Values[0]
public double Value;
}
Samples
Creating a time series index using
TimeSeriesIndexDefinition
:documentStore.Maintenance.Send(new PutIndexesOperation(
new TimeSeriesIndexDefinition
{
Name = "Stocks_ByTradeVolume",
Maps = {
"from ts in timeSeries.Companies.StockPrice " +
"from entry in ts.Entries " +
"select new " +
"{ " +
" TradeVolume = entry.Values[4], " +
" entry.Timestamp.Date " +
"}"
}
}));
AbstractTimeSeriesIndexCreationTask
public class Stocks_ByTradeVolume : AbstractTimeSeriesIndexCreationTask<Company>
{
public Stocks_ByTradeVolume()
{
AddMap("StockPrice",
timeseries => from ts in timeseries
from entry in ts.Entries
select new
{
TradeVolume = entry.Values[4],
entry.Timestamp.Date
});
}
}
AbstractMultiMapTimeSeriesIndexCreationTask
public class Vehicles_ByLocation : AbstractMultiMapTimeSeriesIndexCreationTask
{
public Vehicles_ByLocation()
{
AddMap<Plane>(
"GPS_Coordinates",
timeSeries => from ts in timeSeries
from entry in ts.Entries
select new
{
Latitude = entry.Values[0],
Longitude = entry.Values[0],
entry.Timestamp
});
AddMap<Ship>(
"GPS_Coordinates",
timeSeries => from ts in timeSeries
from entry in ts.Entries
select new
{
Latitude = entry.Values[0],
Longitude = entry.Values[0],
entry.Timestamp
});
}
}
AbstractJavaScriptTimeSeriesIndexCreationTask
public class Company_TradeVolume_ByDate : AbstractJavaScriptTimeSeriesIndexCreationTask
{
public Company_TradeVolume_ByDate()
{
Maps = new HashSet<string> { @"
timeSeries.map('Companies', 'StockPrices', function (ts) {
return ts.Entries.map(entry => ({
Volume: entry.Values[0],
Date: entry.Timestamp,
Company: ts.DocumentId
}));
})"
};
}
}
Map-Reduce Time Series Index
public class TradeVolume_PerDay_ByCountry :
AbstractTimeSeriesIndexCreationTask<Company, TradeVolume_PerDay_ByCountry.Result>
{
public class Result
{
public double TradeVolume { get; set; }
public DateTime Date { get; set; }
public string Country { get; set; }
}
public TradeVolume_PerDay_ByCountry()
{
AddMap(
"StockPrice",
timeSeries => from ts in timeSeries
let company = LoadDocument<Company>(ts.DocumentId)
from entry in ts.Entries
select new Result
{
TradeVolume = entry.Values[4],
Date = entry.Timestamp.Date,
Country = company.Address.Country
});
Reduce = results =>
from r in results
group r by new { r.Date, r.Country } into g
select new Result
{
TradeVolume = g.Sum(x => x.TradeVolume),
Date = g.Key.Date,
Country = g.Key.Country
};
}
}
Yet another way to create a time series index is to create a
TimeSeriesIndexDefinitionBuilder
, and use it to create a
TimeSeriesIndexDefinition
.
var TSIndexDefBuilder =
new TimeSeriesIndexDefinitionBuilder<Company>("Stocks_ByTradeVolume");
TSIndexDefBuilder.AddMap("StockPrice",
timeseries => from ts in timeseries
from entry in ts.Entries
select new
{
TradeVolume = entry.Values[4],
entry.Timestamp.Date
});
documentStore.Maintenance.Send(new PutIndexesOperation(
TSIndexDefBuilder.ToIndexDefinition(documentStore.Conventions)));