Use the Lindorm Time Series Database (TSDB) SDK to build and run queries against your time series data. This document covers synchronous and asynchronous queries, result ordering, and how to retrieve the latest data point for a time series.
Key concepts
| Concept | Class | Description |
|---|---|---|
| Query | Query | The top-level query object. Holds a time range and one or more sub queries. |
| Sub query | SubQuery | Defines what data to retrieve: a metric, an aggregator, optional downsampling, and tag filters. A single Query can contain multiple sub queries. |
| Aggregator | Aggregator | An enumeration of aggregation functions. Common values: AVG, SUM, NONE. |
Build a query
Construct a Query object using the builder pattern. At minimum, specify a time range and at least one sub query.
Query query = Query
.timeRange(startTime, endTime) // Specify the time range during which you want to query data.
.sub(SubQuery.metric("hello").aggregator(Aggregator.AVG).tag("tagk1", "tagv1").build())
.sub(SubQuery.metric("world").aggregator(Aggregator.SUM).tag("tagk2", "tagv2").build())
.build();Sub query parameters
Each SubQuery accepts the following parameters:
| Parameter | Type | Description | Example |
|---|---|---|---|
metric | String | The metric name to query. | "cpu.usage" |
aggregator | Aggregator | The aggregation function to apply. | Aggregator.AVG |
downsample | String | Reduces data density by resampling. Format: <interval><unit>-<aggregator>. For example, 60m-avg produces one average per 60 minutes. | "60m-avg" |
tag | String, String | Filters results to a specific tag key-value pair. Call multiple times to add more filters. | "region", "us-west" |
Example sub query with all parameters:
SubQuery subQuery = SubQuery
.metric("test-metric")
.aggregator(Aggregator.AVG)
.downsample("60m-avg") // One average per 60 minutes
.tag("tagk1", "tagv1")
.tag("tagk2", "tagv2")
.build();Run a synchronous query
Call tsdb.query(query) to run a query in thread synchronization mode. The method blocks until results are returned.
List<QueryResult> result = tsdb.query(query);
System.out.println("Returned result" + result);Run an asynchronous query
Pass a QueryCallback to tsdb.query() to run the query asynchronously. The SDK invokes response() when results are available.
QueryCallback cb = new QueryCallback() {
@Override
public void response(Query input, List<QueryResult> result) {
System.out.println("Query parameters:" + input);
System.out.println("Returned result:" + result);
}
};
tsdb.query(query, cb);Query result structure
tsdb.query() returns List<QueryResult>. Each QueryResult corresponds to one sub query.
Call getDps() on a QueryResult to obtain the data points.
Sort query results by timestamp
By default, getDps() returns data points in an unordered map. Use getOrderDps() to get a timestamp-sorted collection:
| Method | Order |
|---|---|
getDps() | Unordered |
getOrderDps() | Ascending (oldest first) |
getOrderDps(true) | Descending (newest first) |
The following example retrieves the same data points in all three orderings:
Query query = Query
.timeRange(current - 1000, start + 1000)
.sub(SubQuery.metric(metric).aggregator(Aggregator.NONE).tag(tags).build())
.build();
try {
List<QueryResult> result = tsdb.query(query);
for (QueryResult queryResult : result) {
// Unordered data points
System.out.println(queryResult.getDps());
System.out.println("-------------");
// Ascending order by timestamp
System.out.println(queryResult.getOrderDps());
System.out.println("-------------");
// Descending order by timestamp
System.out.println(queryResult.getOrderDps(true));
}
} catch (HttpUnknowStatusException e) {
e.printStackTrace();
}Query the latest data point
tsdb.queryLast() returns one LastDataValue per time series — the most recent data point before a given timestamp.
There are two ways to identify which time series to query:
| Method | When to use |
|---|---|
| By metric and tags | First time querying, or when you don't have TSUIDs yet |
| By TSUID | Subsequent queries for the same time series |
Recommended workflow: Query by metric and tags first, then save the TSUIDs from the result for use in subsequent queries.
By metric and tags
Specify the metric name and tag filters in a LastPointSubQuery:
// Define tag filters
Map<String, String> tags = new HashMap<String, String>();
tags.put("uid", "1");
tags.put("id", "6");
String metric = "test.1";
// Build and run the query
LastPointQuery query = LastPointQuery.builder()
.timestamp(1537520409729l) // Query the latest point before this timestamp
.msResolution(true) // Interpret the timestamp as milliseconds
.sub(LastPointSubQuery.builder(metric, tags).build())
.build();
List<LastDataValue> lastDataValues = tsdb.queryLast(query);
System.out.println(lastDataValues);The result includes the TSUID for each matched time series. Save these TSUIDs to use in subsequent queries.
By TSUID
If you already have TSUIDs from a previous query, pass them directly:
// TSUIDs obtained from a prior queryLast() call
List<String> tsuids = new ArrayList<String>();
tsuids.add("10000B7C000095000081****FF00006F");
LastPointQuery query = LastPointQuery.builder()
.timestamp(1537520409729l)
.msResolution(true)
.sub(LastPointSubQuery.builder(tsuids).build())
.build();
List<LastDataValue> lastDataValues = tsdb.queryLast(query);
System.out.println(lastDataValues);