Time Series Querying


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 type
TimeSeriesRawResult 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 a TimeSeriesRawResult 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 a TimeSeriesAggregationResult 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.