Find digital twins in the Digital Twin Registry
Digital twins can be queried at the /registry-api/v2/twins
endpoint. This endpoint supports filtering and paging in order to give the client control about how many and which resources it wants to retrieve.
Filtering reduces the amount of retrieved entities by given criteria, paging returns a subset of the results. With sorting, the retrieved results are returned in a predefined order.
Filtering
The Digital Twin Registry API supports filtering via RQL (Resource Query Language).
Filtering of results is specified by the value of the query parameter filter
.
The general form of the query string looks as follows:
filter={filter expression}&option=limit({start},{count})
If there is an issue processing the filter expression, the response will provide details on the error.
The value is an expression that uses one of the following operators:
-
Comparison:
eq
,in
,ne
,gt
,ge
,lt
,le
,like
andlikeIgnoreCase
; -
Logical:
and
,or
andnot
.
The following list illustrates some example filter expressions:
-
likeIgnoreCase(description,"*my device*")
: All digital twins that have adescription
containing "my device" -
in(twinCategory,"Machine","Device")
: All digital twins that have atwinCategory
of either "Machine" or "Device" -
and(eq(twinCategory,"Printer"), eq(labels.name,"Floor1"))
: All digital twins with giventwinCategory
and at least one label with nameFloor1
Supported properties
Starting root | Properties |
---|---|
Digital twin |
id, twinType, twinCategory, description, aspects, localIdentifiers, labels, groups (are digital twin groups - shortcut for groupMemberships.group) |
Local identifier |
id, digitalTwin, hash, valueSet, localIdentifierKeyPairs.<key> |
Label |
id, name, digitalTwin |
Digital twin group |
id, name |
Aspect |
id, modelReference, digitalTwin, httpEndpoints, mqttEndpoints |
Aspect Model reference |
urn |
Aspect HTTP endpoint |
id, aspect, twin |
Aspect MQTT endpoint |
id, aspect |
Aspect template |
id, name, modelReference, httpEndpointTemplates, mqttEndpointTemplates, groups (are digital twin groups - shortcut for templateGroupMemberships.digitalTwinGroup) |
Model reference template |
id, urn |
HTTP endpoint template |
id, aspectTemplate |
MQTT endpoint template |
id, aspectTemplate |
Group statistic |
id |
Each defined endpoint with RQL filtering specifies which is the starting root.
Supported operators:
-
ID properties - all comparison operators except
like
andlikeIgnoreCase
-
Label.name -
eq
,in
,ne
-
DigitalTwin.twinType, DigitalTwin.twinCategory, DigitalTwin.description, LocalIdentifier.hash, LocalIdentifier.valueSet, LocalIdentifier,localIdentifierKeyPairs.<key>, Aspect.modelReference.urn, AspectTemplate.modelReference.urn- all comparison operators
-
Relation properties - are the properties used to cascade to another entity. Examples:
-
starting from Aspect:
eq(digitalTwin.labels.name, "Floor1")
-
starting from DigitalTwin:
in(digitalTwin.aspects.httpEndpoints.id, 1, 2)
,filter=eq(digitalTwin.aspects.modelReference.urn, "urn:samm:com.bosch.nexeed.digitaltwin:aspect-model:Aspect:1.1.0")
-
starting from AspectTemplate:
like(groups.name, "Printer*")
-
If additional properties are required, please contact us at support.semantic-stack@bosch.com.
Paging
A number of API endpoints provide cursor pagination.
Cursor pagination
Cursor pagination methodology partition the entities of a larger dataset, based on various criteria.
-
This type of pagination is broadly intended for continuous pagination and therefore lacks the option of selecting a specific page index, in favor of basing the pagination on a specific cursor, provided by the back-end in the first response (assuming the dataset has more than one page)
-
In cursor pagination, once the client obtains the first page and a cursor for the next one, it can send the next request with that cursor as an argument, in order to fetch the next page
-
Cursor pagination avails of logarithmic solutions to scroll through a sorted dataset, which tends to perform increasingly better than offset pagination, the larger the dataset and the closer to its end data is being fetched
-
In other words, cursor pagination is preferable in the vast majority of use cases
One criterion to cursor pagination methodology is the size of the page, expressed as:
-
the
limit
argument expressed as a query parameter in non-bulk APIs using cursor pagination (e.g.,?limit=50
) -
the
limit
argument expressed in the request body for bulk APIs using cursor pagination (e.g.,"limit": 50
)
There is a small difference between the Digital Twin Registry API and the Bulk API:
-
the bulk API endpoints feature both offset and cursor pagination based on the request parametrization: if RQL
limit(x,y)
is used, offset pagination will be used - conversely, if thelimit
andcursor
arguments are used in the request body, cursor pagination will be used -
the non-bulk API endpoints featuring cursor pagination for the
v2
API
Finally, the page size defaults are featured similarly, but not identically for the two methodologies:
Operation type | Cursor-based | Default page size | Maximum page size |
---|---|---|---|
Bulk |
Yes |
Relevant bulk max quota for that endpoint |
Relevant bulk max quota for that endpoint |
Bulk |
No |
No default: desired page size must be specified in RQL |
Relevant bulk max quota for that endpoint |
Non-bulk |
Yes |
500 |
500 |
-
In all cases, when a desired page size exceeds the maximum page size or quota, the request will fail with an error
-
For specific information about the bulk API quotas, please refer to the API documentation
Cursor pagination interaction lifecycle
This section summarizes the typical exchanges between client and server when cursor pagination is involved. The two small sections above underline the similarities and small differences between bulk and non-bulk APIs in that process.
Bulk APIs
-
The client requests data via a cursor-paginating endpoint, optionally parameterizing the request with:
-
a
limit
within the supported bulk quota (defaults to500
elements if absent) -
an RQL
filter
query (defaults to "all elements of that type" if absent)
-
-
The server responds with the first page of elements
-
If more elements are present in the dataset, the response body will contain a
nextCursor
value, expressed as a string
-
-
If the server response contains a
nextCursor
value, the client copies it ascursor
in the body of the next request -
In turn, the server provides a page of elements after that
cursor
, and again thenextCursor
value in the next response, if any more pages are available -
This exchange iterates ad lib. until the server stops providing a
nextCursor
value in the response -
Once no
nextCursor
value is available to the client, it "knows" it has reached the end of the desired dataset, and can stop sending further requests
Non-bulk APIs
-
The client requests data via a cursor-paginating endpoint, optionally parameterizing the request with:
-
a
limit
value up to, and defaulting to500
elements -
an RQL
filter
query (defaults to "all elements of that type" if absent)
-
-
The server responds with the first page of elements
-
If more elements are present in the dataset, the response body will contain a
nextCursor
value, expressed as a string
-
-
If the server response contains a
nextCursor
value, the client copies it ascursor
in the query parameters of the next request -
In turn, the server provides a page of elements after that
cursor
, and again thenextCursor
value in the next response, if any more pages are available -
This exchange iterates ad lib. until the server stops providing a
nextCursor
value in the response -
Once no
nextCursor
value is available to the client, it "knows" it has reached the end of the desired dataset, and can stop sending further requests
Sorting
With user-defined sorting, the client is responsible for preventing an arbitrary order of the retrieved results.
User-defined sorting can be achieved by using the RQL options operator with the keyword sort
.
Two different use cases exist:
-
Use case 1: The client provides sorting information via the
sort
keyword.-
Example:
option=sort(-id)
-
Sort direction for a property can be given with:
-
+
for ascending order -
-
for descending order
-
-
-
Use case 2: The client does not provide any sorting information.
-
The results will be sorted by default sorting.
-
Default sorting happens by ID and in ascending order, which implicitly also yields an ascending order by creation time.
-
If sorting is used with a cursor, the sort expression must NOT change from the previous request. Otherwise incorrect results or an error may occur. |
Note that:
-
User-defined sorting may result in longer response times.
-
Even if the client provides sorting information, arbitrary ordering can still occur if parallel accesses (deleting or adding elements) take place.
-
If it is important that ALL elements are returned, user-defined sorting cannot be used.
Currently, only reviewed attributes from the root entity can be used. If a desired attribute is not available, please contact us.
Select
The select operator trims each response down to the set of attributes defined in the arguments of the query. User-defined select can be requested via RQL for a root entity. All child entities will then not be loaded.
This means that response times can be significantly improved if only the requested information is returned.
Example:
Load only twin IDs (select) and do that only for twins that have the label blue
assigned (filter).
select=id&filter=eq(labels.name, "blue")