Time Series Querying
-
Time series data can be effectively queried in RavenDB, allowing users to access and analyze information based on specific time intervals.
-
Time series queries can be made using:
- The
query
method - Or directly through RQL,
which can be provided to a
rawQuery
or executed from the Studio's Query view.
- The
-
In this page:
Learn more about time series queries in the section dedicated to this subject.
Query
Query usage
- Open a session
-
Call
session.query
:- Provide a query predicate to locate documents whose time series you want to query
- Use
selectTimeSeries
to choose a time series and project time series data - Execute the query
-
Results will be in the form:
TimeSeriesRawResult
for non-aggregated data, or -TimeSeriesAggregationResult
for aggregated data
- Note:
The RavenDB client translates the query to RQL before transmitting it to the server for execution.
Query examples
-
This query filters users by their age and retrieves their HeartRates time series.
// Define the time series query part (expressed in RQL): const tsQueryText = ` from HeartRates where Tag == "watches/fitbit"`; // Define the high-level query: const query = session.query({ collection: "users" }) .whereLessThan("age", 30) // Call 'selectTimeSeries' and pass it: // * the time series query text // * the `TimeSeriesRawResult` return type .selectTimeSeries(b => b.raw(tsQueryText), TimeSeriesRawResult); // Execute the query: const results = await query.all(); // Access entries results: rawResults = results[0]; assert.equal((rawResults instanceof TimeSeriesRawResult), true); const tsEntry = rawResults.results[0]; assert.equal((tsEntry instanceof TimeSeriesEntry), true); const tsValue = tsEntry.value;
from "users" where age < 30 select timeseries( from "HeartRates" where Tag == "watches/fitbit" )
-
In this example, we select a 5-minute range from the HeartRates time series.
const startTime = new Date(); const endTime = new Date(startTime.getTime() + 5 * 60_000); // Define the time series query text: const tsQueryText = ` from HeartRates between $start and $end`; // Define the query: const query = session.query({ collection: "users" }) // Call 'selectTimeSeries' and pass it: // * the time series query text // * the `TimeSeriesRawResult` return type .selectTimeSeries(b => b.raw(tsQueryText), TimeSeriesRawResult) // Add the parameters content .addParameter("start", startTime) .addParameter("end", endTime); // Execute the query: const results = await query.all();
from "Users" select timeseries( from "HeartRates" between "2024-05-19T18:13:17.466Z" and "2024-05-19T18:18:17.466Z" )
-
In this example, we retrieve a company's stock trade data.
Note the usage of named values, so we may address trade Volume by name.
This example is based on the sample entries that were entered in this example.
const oneDay = 24 * 60 * 60 * 1000; const startTime = new Date(); const endTime = new Date(startTime.getTime() + 3 * oneDay); // Note: the 'where' clause must come after the 'between' clause const tsQueryText = ` from StockPrices between $start and $end where Tag == "AppleTech"`; const query = session.query({ collection: "companies" }) .whereEquals("address.city", "New York") .selectTimeSeries(b => b.raw(tsQueryText), TimeSeriesRawResult) .addParameter("start", startTime) .addParameter("end", endTime); // Execute the query: const results = await query.all(); // Access entries results: const tsEntries = results[0].results; const volumeDay1 = tsEntries[0].values[4]; const volumeDay2 = tsEntries[1].values[4]; const volumeDay3 = tsEntries[2].values[4];
const oneDay = 24 * 60 * 60 * 1000; const startTime = new Date(); const endTime = new Date(startTime.getTime() + 3 * oneDay); // Note: the 'where' clause must come after the 'between' clause const tsQueryText = ` from StockPrices between $start and $end where Tag == "AppleTech"`; const query = session.query({ collection: "companies" }) .whereEquals("address.city", "New York") .selectTimeSeries(b => b.raw(tsQueryText), TimeSeriesRawResult) .addParameter("start", startTime) .addParameter("end", endTime); // Execute the query: const results = await query.all(); // Access entries results: const tsEntries = results[0].results; // Call 'asTypedEntry' to be able to access the entry's values by their names // Pass the class type (StockPrice) const volumeDay1 = tsEntries[0].asTypedEntry(StockPrice).value.volume; const volumeDay2 = tsEntries[1].asTypedEntry(StockPrice).value.volume; const volumeDay3 = tsEntries[2].asTypedEntry(StockPrice).value.volume;
from "companies" where address.city == "New York" select timeseries( from StockPrices between $start and $end where Tag == "AppleTech" ) {"start":"2024-05-20T07:54:07.259Z","end":"2024-05-23T07:54:07.259Z"}
-
In this example, we group heart-rate data of people above the age of 72 into 1-day groups, For each group, we retrieve the number of measurements, the minimum, maximum, and average heart rate.
const oneDay = 24 * 60 * 60 * 1000; const startTime = new Date(); const endTime = new Date(startTime.getTime() + 10 * oneDay); const tsQueryText = `from HeartRates between $start and $end where Tag == "watches/fitbit" group by "1 day" select count(), min(), max(), avg()`; const query = session.query({ collection: "users" }) .whereGreaterThan("age", 72) // Call 'selectTimeSeries' and pass it: // * the time series query text // * the `TimeSeriesAggregationResult` return type .selectTimeSeries(b => b.raw(tsQueryText), TimeSeriesAggregationResult) .addParameter("start", startTime) .addParameter("end", endTime); // Execute the query: const results = await query.all(); const aggregatedResults = results[0].results; const averageForDay1 = aggregatedResults[0].average[0]; const averageForDay2 = aggregatedResults[1].average[0];
from "users" where age > 72 select timeseries( from HeartRates between $start and $end where Tag == "watches/fitbit" group by '1 day' select count(), min(), max(), avg() ) {"start":"2024-05-20T09:32:58.951Z","end":"2024-05-30T09:32:58.951Z"}
Query syntax
The session.query
syntax is available here.
Extend the session.query
method with selectTimeSeries()
.
selectTimeSeries(timeSeriesQuery, projectionClass);
Parameter | Type | Description |
---|---|---|
timeSeriesQuery | (builder) => void |
The time series query builder |
projectionClass | object |
The query result typeTimeSeriesRawResult or TimeSeriesAggregationResult |
The time series query builder has one method:
raw(queryText);
Parameter | Type | Description |
---|---|---|
queryText | string |
The time series query part, expressed in RQL. |
Return value | Description |
---|---|
TimeSeriesRawResult[] |
The returned value for non-aggregated data |
TimeSeriesAggregationResult[] |
The returned value for aggregated data |
class TimeSeriesRawResult {
results; // TimeSeriesEntry[]
asTypedResult>(clazz);
}
class TimeSeriesAggregationResult extends TimeSeriesQueryResult {
results; // TimeSeriesRangeAggregation[];
asTypedEntry(clazz);
}
RawQuery
RawQuery usage
- Open a session
- Call
session.advanced.rawQuery
, pass it the raw RQL that will be sent to the server -
Results will be in the form:
TimeSeriesRawResult
for non-aggregated data, or -TimeSeriesAggregationResult
for aggregated data
- Note:
The raw query transmits the provided RQL to the server as is, without checking or altering its content.
RawQuery examples
-
In this example, we retrieve all HearRates time series for all users under 30.
const rql = `from users where age < 30 select timeseries( from HeartRates )`; const query = session.advanced.rawQuery(rql, TimeSeriesRawResult); const result = await query.all();
from users where age < 30 select timeseries( from HeartRates )
-
In this example, a raw RQL query retrieves 24 hours of heart rate data from users under 30.
The query does not aggregate data, so results are in the form of aTimeSeriesRawResult
list.
We define an offset, to adjust retrieved results to the client's local time-zone.const rql = ` declare timeseries getHeartRates(user) { from user.HeartRates between $start and $end offset "03:00" } from users as u where age < 30 select getHeartRates(u)`; const startTime = new Date(); const endTime = new Date(startTime.getTime() + 24 * 60 * 60 * 1000); const query = session.advanced.rawQuery(rql, TimeSeriesRawResult) .addParameter("start", startTime) .addParameter("end", endTime); const result = await query.all();
const rql = ` from Users as u where Age < 30 select timeseries ( from HeartRates between $start and $end offset "03:00" )`; const startTime = new Date(); const endTime = new Date(startTime.getTime() + 24 * 60 * 60 * 1000); const query = session.advanced.rawQuery(rql, TimeSeriesRawResult) .addParameter("start", startTime) .addParameter("end", endTime); const result = await query.all();
// declare syntax // ============== declare timeseries getHeartRates(user) { from user.HeartRates between $start and $end offset '03:00' } from users as u where age < 30 select getHeartRates(u) {"start":"2024-05-20T11:52:22.316Z","end":"2024-05-21T11:52:22.316Z"} // select syntax // ============= from Users as u where Age < 30 select timeseries ( from HeartRates between $start and $end offset "03:00" ) {"start":"2024-05-20T11:55:56.701Z","end":"2024-05-21T11:55:56.701Z"}
-
In this example, the query aggregates 7 days of HeartRates entries into 1-day groups.
From each group, two values are selected and projected to the client:
the min and max hourly HeartRates values.
The aggregated results are in the form of aTimeSeriesAggregationResult
list.const rql = ` from users as u select timeseries( from HeartRates between $start and $end group by '1 day' select min(), max() offset "03:00" )`; const oneDay = 24 * 60 * 60 * 1000; const startTime = new Date(); const endTime = new Date(startTime.getTime() + 7 * oneDay); const query = session.advanced.rawQuery(rql, TimeSeriesRawResult) .addParameter("start", startTime) .addParameter("end", endTime); const result = await query.all();
from users as u select timeseries( from HeartRates between $start and $end group by '1 day' select min(), max() offset "03:00" ) {"start":"2024-05-20T12:06:40.595Z","end":"2024-05-27T12:06:40.595Z"}
RawQuery syntax
session.rawQuery(query);
Parameter | Type | Description |
---|---|---|
query | string |
The RQL query string |
The return value is the same as listed under the query syntax.