# Data Access API Examples
This page discusses mostly the Warm Path endpoint of the Data Access API. The DA API endpoint retrieves both raw and aggregate timeSeries warm data. You can also get just the last value of a specified variable. Some of the discussed cases include best practices that you should follow while designing your queries. At the end of the article, you will also find more best practices applicable to any query you use.
# Get Raw Telemetry
Use the select
object with the properties field (see below) to choose the
properties that you want to see in response. Please note that you cannot use the
properties field in the select object along with the aggregate function
properties of min, max, avg, sum, first, last, or count; it is either/or. Either
you have the properties field or you have one or many of the aggregate function
properties.
# Request
{
"date": {
"from": "<string>",
"to": "<string>"
},
"filter": "<string>",
"select": {
"properties": "<string>"
},
"orderBy": {
"property": "<string>",
"order": "<string>"
},
"limit": "<int>"
}
# Example
In this example, suppose the client has sent in a request object as follows:
{
"date": {
"from": "2018-08-01T00:00:00Z",
"to": "2018-08-31T23:59:59Z"
},
"filter": "",
"select": {
"properties": "objectId,model"
},
"limit": "100"
}
The response for this request will be:
{
"data": [
{
"objectId": "<string>",
"model": "<string>"
}
]
}
The client can also send in a request with custom properties as follows:
{
"date": {
"from": "2018-08-01T00:00:00Z",
"to": "2018-08-31T23:59:59Z"
},
"filter": "",
"select": {
"properties": "objectId,model,mycustomproperty"
},
"limit": "100"
}
The response for this request will be:
{
"data": [
{
"objectId": "<string>",
"model": "<string>",
"mycustomproperty": "<T>"
}
]
}
where T is whatever type that this property returns from the database.
# Get Last Value
There are cases where you'd want to get just the last value of some variable.
You can do that using select.last
filtering.
# Example
The following request will fetch the last value of "voltage" variable of some object.
{
"filter": "objectId='22ab830b-6fc6-4bf5-9579-8ae38088074a' AND variable='voltage' AND model='abb.ability.device'",
"date": {
"from": "0001-01-01T00:00:00Z"
},
"select": {
"last": "value, timestamp"
},
"groupBy": {
"properties": "objectId, variable, model"
}
}
If the object and the property exist (and have data), the response will be as follows:
{
"data": [
{
"objectId": "22ab830b-6fc6-4bf5-9579-8ae38088074a",
"variable": "voltage",
"model": "abb.ability.device",
"last": {
"value": 34.291116909259515,
"timestamp": "2020-12-10T23:59:50"
}
}
]
}
If there is no data, you wil get an empty array:
{
"data": []
}
TIP
You can try this request on the API Playground.
# Best Practices
Below you can find some recommendations that will improve the performance of your Last Value queries (when Redis is configured as the Last Value provider):
Include the
model
in your filter - whenever your case allows it, include themodel
in your query to improve the performance of retrieving the data.For example, instead of just using
objectId='a0707c42-e415-4e97-b777-30135dfde51e'
, useobjectId='a0707c42-e415-4e97-b777-30135dfde51e' AND model='abb.ability.device'
.Use
STARTS_WITH
/ENDS_WITH
/HAS
only when necessary in your filter - these operators are quite costly in terms of performance. If you do not have to use them, don't.For example, instead of using
variable STARTS_WITH 'utilization.'
, usevariable = 'utilization.memory' OR variable = 'utilization.cpu'
.Avoid using
to
orfrom
in the Last Known Value queries unless you have a particular use case for that.
For example, when you setto
to a specific date, and the last event change happens after that date, the query will return an empty response.Understanding the behavior of the time range filter
When using the Redis Cache to retrieve last values for alarms, events, and variables, responses will be returned if their time value falls between the specified
from
andto
time values. When you don't specifyfrom
orto
value, all times are considered. However, there may be cases where thefrom
time is used, for example, to see any last values from the last day. Another example would be to check whether certain alarms or events were last reported between a specificfrom
andto
time.Redis Cache keeps data only for 24 hours.
# Get Aggregate Telemetry
Retrieves aggregate warm data for the constructed request. This request object for this endpoint has many variations and capabilities. Descriptions of the possibilities follow.
# Request
{
"date": {
"from": "<string>",
"to": "<string>"
},
"filter": "<string>",
"select": {
"count": "",
"min": "<string>",
"max": "<string>",
"first": "<string>",
"sum": "<string>",
"avg": "<string>",
},
"groupBy": {
"time": "<string>",
"properties": "<string>"
},
"orderBy": {
"property": "<string>",
"order": "<string>"
},
"limit": "<int>"
}
# Request Constructions
The aggregate requests can be constructed to retrieve a grouped by the histogram of results, a histogram with no grouping, grouping without a histogram, or what's known as a fleet query which is no grouping and no histogram. Each construction with examples is given below.
# Histogram with Grouping
Note: When using a last known state query with the Redis provider, grouping by a histogram (i.e. groupBy with a time request) is not supported.
# Request Example
{
"date": {
"from": "2018-01-01T09:00:00.000Z",
"to": "2018-08-03T09:59:59.000Z"
},
"filter": "",
"select": {
"min": "value",
"max": "value"
},
"groupBy": {
"time": "1h",
"properties": "objectId,variable"
},
"orderBy": {
"property": "timestamp",
"order": "asc"
},
"limit": 10000
}
# Response Example
{
"data": [
{
"objectId": "17c303d6-1667-4f1a-9ec3-0958d3f1b7b5",
"variable": "MT00",
"timestamp": "2018-01-10T11:00:00Z",
"min": {
"value": 0
},
"max": {
"value": 0
}
},
{
"objectId": "18c303d6-1667-4f1a-9ec3-0958d3f1b7b5",
"variable": "MT0",
"timestamp": "2018-01-11T02:00:00Z",
"min": {
"value": 64
},
"max": {
"value": 64
}
}
]
}
# Histogram with Grouping and Multiple Properties in a Single Aggregate
# Request Example
{
"date": {
"from": "2018-01-01T09:00:00.000Z",
"to": "2018-10-31T09:59:59.000Z"
},
"filter": "",
"select": {
"last": "value,timestamp"
},
"groupBy": {
"properties": "objectId,variable"
}
}
# Response Example
{
"data": [
{
"objectId": "00334ce8-20e4-4947-bc0b-092dcb131912",
"variable": "temperature.temp0",
"last": {
"value": 19,
"timestamp": "2018-10-29T05:49:46.0922082Z"
}
},
{
"objectId": "00334ce8-20e4-4947-bc0b-092dcb131912",
"variable": "temperature.temp1",
"last": {
"value": 20,
"timestamp": "2018-10-29T05:54:46.0922082Z"
}
}
]
}
# Histogram without Grouping
# Request Example
{
"date": {
"from": "2018-01-01T09:00:00.000Z",
"to": "2018-08-03T09:59:59.000Z"
},
"filter": "",
"select": {
"min": "value",
"max": "value"
},
"groupBy": {
"time": "1h"
},
"orderBy": {
"property": "timestamp",
"order": "asc"
},
"limit": 10000
}
# Response Example
{
"data": [
{
"timestamp": "2018-01-10T11:00:00Z",
"min": {
"value": 0
},
"max": {
"value": 0
}
},
{
"timestamp": "2018-01-11T02:00:00Z",
"min": {
"value": 64
},
"max": {
"value": 64
}
}
]
}
# Grouping without Histogram
# Request Example
{
"date": {
"from": "2018-01-01T09:00:00.000Z",
"to": "2018-08-03T09:59:59.000Z"
},
"filter": "",
"select": {
"min": "value",
"max": "value",
"last": "value"
},
"groupBy": {
"properties": "objectId,variable"
},
"orderBy": {
"property": "timestamp",
"order": "asc"
},
"limit": 10000
}
# Response Example
{
"data": [
{
"objectId": "17c303d6-1667-4f1a-9ec3-0958d3f1b7b5",
"variable": "MT00.979166666666667",
"min": {
"value": 0.065403129230141341
},
"max": {
"value": 0.065403129230141341
},
"last": {
"value": 0.065403129230141341
}
},
{
"objectId": "18c303d6-1667-4f1a-9ec3-0958d3f1b7b5",
"variable": "MT0",
"min": {
"value": 1
},
"max": {
"value": 1
},
"last": {
"value": 1
}
},
{
"objectId": "2a85ecee-97e5-4151-96b2-8b56ba78613d",
"variable": "brokenRotorIndex",
"min": {
"value": 5
},
"max": {
"value": 5
},
"last": {
"value": 5
}
}
]
}
# Fleet Query
# Request Example
{
"date": {
"from": "2018-01-01T09:00:00.000Z",
"to": "2018-08-03T09:59:59.000Z"
},
"filter": "variable='skinTemperature'",
"select": {
"min": "value",
"max": "value",
"last": "value"
},
"orderBy": {
"property": "timestamp",
"order": "asc"
},
"limit": 10000
}
# Response Example
{
"data": [
{
"min": {
"value": 0.065403129230141341
},
"max": {
"value": 0.065403129230141341
},
"last": {
"value": 0.065403129230141341
}
}
]
}
The successful response object will contain either all properties specified in the 'select' clause or all properties specified in the 'group by' clause, plus each function in the 'select' statement will contain the calculated value in the same named property.
# Standard Response Object
{
"data": [
{
"propertyrequested": "<T>"
}
]
}
# Specified Response Object
In this example, suppose the client has sent in a request object as follows:
{
"date": {
"from": "2018-01-01T09:00:00.000Z",
"to": "2018-08-03T09:59:59.000Z"
},
"filter": "",
"select": {
"min": "value",
"max": "value"
},
"groupBy": {
"time": "1h",
"properties": "objectId,variable"
},
"orderBy": {
"property": "timestamp",
"order": "asc"
},
"limit": 10000
}
The response for this request will be:
{
"data": [
{
"timestamp": "2018-07-10T11:00:00Z",
"objectId": "17c303d6-1667-4f1a-9ec3-0958d3f1b7b5",
"variable": "MT00.0416666666666667",
"min": {
"value": 0.13052619222005157
},
"max": {
"value": 0.13052619222005157
}
},
{
"timestamp": "2018-07-11T04:00:00Z",
"objectId": "18c303d6-1667-4f1a-9ec3-0958d3f1b7b5",
"variable": "MT0",
"min": {
"value": 15
},
"max": {
"value": 15
}
}
]
}
In this example, suppose the client has sent in a request object as follows:
{
"date": {
"from": "2018-01-01T09:00:00.000Z",
"to": "2018-08-03T09:59:59.000Z"
},
"filter": "",
"select": {
"max": "value,timestamp",
"last": "value,timestamp"
},
"groupBy": {
"properties": "objectId,variable"
},
"orderBy": {
"property": "timestamp",
"order": "asc"
},
"limit": 10000
}
The response for this request will be:
{
"data": [
{
"objectId": "18c303d6-1667-4f1a-9ec3-0958d3f1b7b5",
"variable": "MT0",
"max": {
"value": 95,
"timestamp": "2018-07-11T04:01:35.6034Z"
},
"last": {
"value": 95,
"timestamp": "2018-07-11T04:01:35.6034Z"
}
},
{
"objectId": "2a85ecee-97e5-4151-96b2-8b56ba78613d",
"variable": "brokenRotorIndex",
"max": {
"value": 5,
"timestamp": "2018-05-01T15:12:09.473Z"
},
"last": {
"value": 5,
"timestamp": "2018-05-01T15:12:09.473Z"
}
}
]
}
# Best Practices
Below you can find a few recommendations on how to make your Warm Path queries efficient. Following these might improve the response times significantly.
- Try to spread your queries in time - instead of sending multiple requests concurrently, try to send them with some delay in between. The Ability Platform uses Azure Time Series Insights component for its Warm Path offering. This Azure component is limited to serving maximum 10 concurrent requests. Sending more requests concurrently to the Data Access API will result in bigger latencies in response.
- When fetching files from the Data Access API (Object Storage or Global Storage), note that the response time is highly dependent on the number of files being stored. If the number of files is very high, you should expect the latencies to grow.
- If a single request contains query for both Warm Path and Last Value, the response will be returned only after the slowest of the requested queries is done.
- When making requests with multiple aggregates, the last value cannot be
included with other aggregates when
groupBy
includes time. - Avoid fleet queries with aggregations if possible. In the case of aggregation queries, do not use large time intervals with small-time breaks, which can cause reaching TSI v1 cardinality limit (which is equal to 150 000).
# Query Expression Support
The default database implementation for warm data is Time Series Insights. It utilizes its own query language which the API translates from the filter property. The filter currently supports every operator of the ABB Ability™ Query Expression Language format.