Querying Time Series Indexes
-
Time series index:
-
STATIC-time-series-indexes can be defined from the Client API or using Studio.
Such an index can be queried in the same way as a regular index that indexes documents.
(See Querying an index). -
AUTO-time-series-indexes are Not generated automatically by the server when making a time series query.
-
-
The contents of the query results:
-
Unlike a document index, where the source data are your JSON documents,
the source data for a time series index are the time series entries within the documents. -
When querying a document index:
the resulting objects are the document entities (unless results are projected). -
When querying a time series index:
each item in the results is of the type defined by the index-entry in the index definition,
(unless results are projected). The documents themselves are not returned.
-
-
In this page:
Sample Index
-
The following is a time series map-index that will be used in the query examples throughout this article.
-
Each index-entry consists of:
- Three index-fields obtained from the "HeartRates" time series entries:
BPM
,Date
, andTag
. - One index-field obtained from the time series segment header:
EmployeeID
. - One index-field obtained from the loaded employee document:
EmployeeName
.
- Three index-fields obtained from the "HeartRates" time series entries:
-
When querying this time series index:
- The resulting items correspond to the time series entries that match the query predicate.
- Each item in the results will be of type
TsIndex.IndexEntry
, which is the index-entry.
Different result types may be returned when the query projects the results.
public class TsIndex : AbstractTimeSeriesIndexCreationTask<Employee>
{
// The index-entry:
// ================
public class IndexEntry
{
// The index-fields:
// =================
public double BPM { get; set; }
public DateTime Date { get; set; }
public string Tag { get; set; }
public string EmployeeID { get; set; }
public string EmployeeName { get; set; }
}
public TsIndex()
{
AddMap("HeartRates", timeSeries =>
from segment in timeSeries
from entry in segment.Entries
let employee = LoadDocument<Employee>(segment.DocumentId)
// Define the content of the index-fields:
// =======================================
select new IndexEntry()
{
BPM = entry.Values[0],
Date = entry.Timestamp,
Tag = entry.Tag,
EmployeeID = segment.DocumentId,
EmployeeName = employee.FirstName + " " + employee.LastName
});
}
}
Querying the index
Query all time series entries:
No filtering is applied in this query.
Results will include ALL entries from time series "HeartRates".
using (var session = store.OpenSession())
{
List<TsIndex.IndexEntry> results = session
// Query the index
.Query<TsIndex.IndexEntry, TsIndex>()
// Query for all entries w/o any filtering
.ToList();
// Access results:
TsIndex.IndexEntry entryResult = results[0];
string employeeName = entryResult.EmployeeName;
double BPM = entryResult.BPM;
}
using (var asyncSession = store.OpenAsyncSession())
{
List<TsIndex.IndexEntry> results = await asyncSession
// Query the index
.Query<TsIndex.IndexEntry, TsIndex>()
// Query for all entries w/o any filtering
.ToListAsync();
}
using (var session = store.OpenSession())
{
List<TsIndex.IndexEntry> results = session.Advanced
// Query the index
.DocumentQuery<TsIndex.IndexEntry, TsIndex>()
// Query for all entries w/o any filtering
.ToList();
}
using (var session = store.OpenSession())
{
List<TsIndex.IndexEntry> results = session.Advanced
// Query the index for all entries w/o any filtering
.RawQuery<TsIndex.IndexEntry>($@"
from index 'TsIndex'
")
.ToList();
}
from index "TsIndex"
Filter query results:
In this example, time series entries are filtered by the query.
The query predicate is applied to the index-fields.
using (var session = store.OpenSession())
{
List<TsIndex.IndexEntry> results = session
.Query<TsIndex.IndexEntry, TsIndex>()
// Retrieve only time series entries with high BPM values for a specific employee
.Where(x => x.EmployeeName == "Robert King" && x.BPM > 85)
.ToList();
}
using (var asyncSession = store.OpenAsyncSession())
{
List<TsIndex.IndexEntry> results = await asyncSession
.Query<TsIndex.IndexEntry, TsIndex>()
// Retrieve only time series entries with high BPM values for a specific employee
.Where(x => x.EmployeeName == "Robert King" && x.BPM > 85)
.ToListAsync();
}
using (var session = store.OpenSession())
{
List<TsIndex.IndexEntry> results = session.Advanced
.DocumentQuery<TsIndex.IndexEntry, TsIndex>()
// Retrieve only time series entries with high BPM values for a specific employee
.WhereEquals(x => x.EmployeeName, "Robert King")
.AndAlso()
.WhereGreaterThan(x => x.BPM, 85)
.ToList();
}
using (var session = store.OpenSession())
{
List<TsIndex.IndexEntry> results = session.Advanced
// Retrieve only time series entries with high BPM values for a specific employee
.RawQuery<TsIndex.IndexEntry>($@"
from index 'TsIndex'
where EmployeeName == 'Robert King' and BPM > 85.0
")
.ToList();
}
from index "TsIndex"
where EmployeeName == "Robert King" and BPM > 85.0
Order query results:
Results can be ordered by any of the index-fields.
using (var session = store.OpenSession())
{
List<TsIndex.IndexEntry> results = session
.Query<TsIndex.IndexEntry, TsIndex>()
// Retrieve time series entries where employees had a low BPM value
.Where(x => x.BPM < 58)
// Order by the 'Date' index-field (descending order)
.OrderByDescending(x => x.Date)
.ToList();
}
using (var asyncSession = store.OpenAsyncSession())
{
List<TsIndex.IndexEntry> results = await asyncSession
.Query<TsIndex.IndexEntry, TsIndex>()
// Retrieve time series entries where employees had a low BPM value
.Where(x => x.BPM < 58)
// Order by the 'Date' index-field (descending order)
.OrderByDescending(x => x.Date)
.ToListAsync();
}
using (var session = store.OpenSession())
{
List<TsIndex.IndexEntry> results = session.Advanced
.DocumentQuery<TsIndex.IndexEntry, TsIndex>()
// Retrieve time series entries where employees had a low BPM value
.WhereLessThan(x => x.BPM, 58)
// Order by the 'Date' index-field (descending order)
.OrderByDescending(x => x.Date)
.ToList();
}
using (var session = store.OpenSession())
{
List<TsIndex.IndexEntry> results = session.Advanced
// Retrieve entries with low BPM value and order by 'Date' descending
.RawQuery<TsIndex.IndexEntry>($@"
from index 'TsIndex'
where BPM < 58.0
order by Date desc
")
.ToList();
}
from index "TsIndex"
where BPM < 58.0
order by Date desc
Project results:
-
Instead of returning the entire
TsIndex.IndexEntry
object for each result item,
you can return only partial fields. -
Learn more about projecting query results in Project Index Query Results.
-
In this example, we query for time series entries with a very high BPM value.
We retrieve entries with BPM value > 100 but return only the EmployeeID for each entry.
using (var session = store.OpenSession())
{
List<string> results = session
.Query<TsIndex.IndexEntry, TsIndex>()
.Where(x => x.BPM > 100)
// Return only the EmployeeID index-field in the results
.Select(x => x.EmployeeID)
// Optionally: call 'Distinct' to remove duplicates from results
.Distinct()
.ToList();
}
using (var asyncSession = store.OpenAsyncSession())
{
List<string> results = await asyncSession
.Query<TsIndex.IndexEntry, TsIndex>()
.Where(x => x.BPM > 100)
// Return only the EmployeeID index-field in the results
.Select(x => x.EmployeeID)
// Optionally: call 'Distinct' to remove duplicates from results
.Distinct()
.ToListAsync();
}
var fieldsToProject = new string[] {
"EmployeeID"
};
using (var session = store.OpenSession())
{
List<EmployeeDetails> results = session.Advanced
.DocumentQuery<TsIndex.IndexEntry, TsIndex>()
.WhereGreaterThan(x => x.BPM, 100)
// Return only the EmployeeID index-field in the results
.SelectFields<EmployeeDetails>(fieldsToProject)
// Optionally: call 'Distinct' to remove duplicates from results
.Distinct()
.ToList();
}
// This class is used when projecting index-fields via DocumentQuery
public class EmployeeDetails
{
public string EmployeeName { get; set; }
public string EmployeeID { get; set; }
}
using (var session = store.OpenSession())
{
List<TsIndex.IndexEntry> results = session.Advanced
// Return only the EmployeeID index-field in the results
.RawQuery<TsIndex.IndexEntry>($@"
from index 'TsIndex'
where BPM > 100.0
select distinct EmployeeID
")
.ToList();
}
from index "TsIndex"
where BPM > 100.0
select distinct EmployeeID
Syntax
-
session.Query
IRavenQueryable<T> Query<T, TIndexCreator>() where TIndexCreator : AbstractCommonApiForIndexes, new();
-
DocumentQuery
IDocumentQuery<T> DocumentQuery<T, TIndexCreator>() where TIndexCreator : AbstractCommonApiForIndexes, new();
Parameter | Description |
---|---|
T | The results class |
TIndexCreator | Index |