Search resources

An IoT developer can search for Things by simple attribute values via the Bosch IoT Things HTTP API. Further, he can define a sort order and the pagination of the search results.

Our search is case sensitive. In case you don't know how exactly the spelling of the namespace, name, attribute, feature etc. is, use the like notation for filtering. See like.

The root resource itself is the endpoint for further search operations.
The filter parameter is optional. If omitted, the search will return all Things on which the currently authenticated user has read permission.

 https://<host>/api/2/search/things?filter=<your-search-criteria>

Example - all things in the living room

 https://<host>/search/things?filter=eq(attributes/location,"living-room") 

Starting with HTTP API v2 the search result is limited to the Things within the namespace (or namespaces) the solution is configured for (see Manage your solution). With the namespaces parameter it is possible to search in other known namespaces.

At the moment we do not support search on array fields.

The search/things/count resource be used to count things.
The filter parameter is optional. If omitted, the search will return all Things on which the currently authenticated user has read permission.

Example - count the things in the living room

 https://.../search/things/count?filter=eq(attributes/location,"living-room") 

The following operations are available over the HTTP API:

The operators provided to compose a search request are described in the following sections.

Following fields help you to more precisely describe what you are actually searching for.

  • thingId
  • policyId
  • all feature IDs
  • all feature properties
  • all attributes
  • _namespace
  • _modified
  • _policy
  • _revision

Tip The fields can be used in a search filter as well as for sorting the results.
See Example 3

This filter parameter defines the search query by aggregation of the following operators.

Please note that whitespaces are only allowed inside of quoted string values.

For example:

eq(attributes/manufacturer, "ACME")

is not allowed because of the whitespace after the comma, but

eq(attributes/manufacturer,"ACME")

and

eq(attributes/manufacturer,"ACME Holding")

are okay.

Relational operators

eq

 eq(<property>, <value>) = <query> 

(i.e. equal to the given value)

Example - things owned by “SID123”

 filter=eq(attributes/manufacturer,"SID123")

ne

 ne(<property>, <value>) = <query> 

(i.e. not equal to the given value)

Example - things with manufacturer different than “SID123”

 filter=ne(attributes/manufacturer,"SID123")

The response will contain only things which do provide an manufacturer attribute (in this case with value 0 or not SID123).

gt

 gt(<property>, <value>) = <query> 

(i.e. greater than to the given value)

Example - things with thing ID greater than “A000”

 filter=gt(thingId,"A000")

ge

 ge(<property>, <value>) = <query> 

(i.e. equal to the given value or greater than it)

Example - things with thing ID “A000” or greater

 filter=ge(thingId,"A000")

lt

 lt(<property>, <value>) = <query> 

(i.e. lower than the given value or equal to it)

Example - things with thing ID lower than “A000”

 filter=lt(thingId,"A000")

le

 le(<property>, <value>) = <query> 

(i.e. lower than the given value)

Example - things with thing ID “A000” or lower

 filter=le(thingId,"A000")

in

 in(<property>, <value>, <value> , ...) = <query> 

(i.e. contains at least one of the values listed)

Example - things with thing ID “A000” or “AB00” or “AZ99”

 filter=in(thingId,"A000","AB00","AZ99")

like

 like(<property>, <value>) = <query> 

(i.e. contains values similar to the expressions listed)

Details concerning the like-operator

The like operator provides some regular expression capabilities for pattern matching Strings.
The following expressions are supported:

  • startswith* ⇒ match at the start of a specific String.
  • *endswith ⇒ match at the end of a specific String.
  • *contains* ⇒ match if contains a specific String.
  • Th?ng ⇒ match for a wildcard character.

Examples

filter=like(attributes/key1,"known-chars-at-start*") 
filter=like(attributes/key1,"*known-chars-at-end")
filter=like(attributes/key1,"*known-chars-in-between*") 
filter=like(attributes/key1,"just-som?-char?-unkn?wn")

exists

 exists(<property>) = <query> 

(i.e. all things in which the given path exists)

Example - things which have a Feature with ID “feature_1”

 filter=exists(features/feature_1)

Example - lamp features which are located in the living-room

 filter=and(exists(features/lamp), eq(attributes/location,"living-room"))

Details on Property

 <property> = url-encoded-string

To search for nested properties, we use JSON Pointer notation (RFC-6901 - https://tools.ietf.org/html/rfc6901).

The following example shows how to search for the sub property location of the parent property attributes with a forward slash as separator:

 eq(attributes/location,"kitchen")

Details on Value

 <value> = <number>, <string>, true, false, null
 <number> = double, integer
 <string> = ", url-encoded-string, "

Comparison of string values

Comparison operators such as gt, ge, lt and le, do not support a special “semantics” of string comparison (e.g. regarding alphabetical or lexicographical ordering). However, you can rely on the alphabetical sorting of strings with the same length (e.g. “aaa” < “zzz”) and that the order stays the same over multiple/different search requests.


Comparison of other data types

Please note that the comparison of other data types is supported by the API, but it only supports comparison of same data types, and does not do any conversion during comparison.

Logical operators

and

 and(<query>,<query>, ...) = <query>   

(i.e. all given values match)

Example - things which are located on the “upper floor” in the “living-room”

 filter=and(eq(attributes/floor,"upper floor"),eq(attributes/location,"living-room"))  

or

 or(<query>,<query>, ...) = <query>  

(i.e. at least one of the given values match)

Example - all things located on the “upper floor”, and all things with location “living-room”

 filter=or(eq(attributes/floor,"upper floor"),eq(attributes/location,"living-room"))

not

not(<query>) = <query>

(i.e. the negation/opposite of the given query)

Example - search for all things with floor different than “upper floor” or without any floor attribute, and location different than “living-room” or without any location attribute

filter=not(eq(attributes/floor,"upper floor"),eq(attributes/location,"living-room"))

When using a negating expression, such as not or ne, (not equal) please keep in mind that you might experience a longer time to get the response. Compared to other search operators we observed longer response times ourselves.

The namespaces parameter is optional.
If omitted, the search field is restricted to all namespaces registered for the solution (correlating to the API token used for the request).

Setting the namespaces parameter allows to specify one or multiple namespaces where to apply the search criteria.

Example - things in specified namespaces

namespaces=com.bosch.si,org.eclipse.ditto

Optional parameter defining one or more options like sorting or pagination:

Sort option

 sort(<+|-><property>,<+|-><property>,...)
  • Use + for an ascending sort order (URL encoded character %2B)
  • Use - for a descending sort order (URL encoded character %2D)

Example - sort the list ascending by the thing ID

 sort(+thingId)

Example - sort the list ascending by an attribute

 sort(+attributes/location)

Example - multiple sort options

 sort(-attributes/location,+thingId)

This expression will sort the list descending by location attribute.
In case there are multiple things with the same location attribute, these are sorted ascending by their ID.

Sorting of string values

Sorting does not support a special “semantics” of string comparison (e.g. regarding alphabetical or lexicographical ordering). However, you can rely on the alphabetical sorting of strings with the same length (e.g. “aaa” < “zzz”) and that the order stays the same over multiple/different search requests.

Sorting of other values

Sorting does not support a special “semantics” of comparison for fields with values of different data types (e.g. numbers vs. strings). However, you can rely on the fact that values of the same type are sorted respectively.



Paging options

size(<count>)

Limits the search results to <count> items.

  • If the paging option is not explicitly specified, the default value size(25) is used,
    i.e. the first 25 results are returned.
  • The maximum allowed count is 200.
cursor(<cursor-id>)

Starts the search at the position of the cursor with ID <cursor-id>. The cursor ID is obtained from the field cursor of a previous response and marks the position after the last entry of the previous search. A response includes no cursor if there are no more results.

If a request has a cursor option, then any included filter or sort option may not differ from the original request of the cursor. Otherwise, the request is rejected.

The meaning of cursor IDs is undefined.

The paging option limit({offset},{count}) is deprecated.
In case you still use the old option, slow queries or timeouts might occur.
Also, the old options might be removed without further notice.

Example 1

Search for all things located in “living-room”, reorder the list to start with the lowest thing ID as the first element, and return the first 5 results.

.../search/things?filter=eq(attributes/location,"living-room")&option=sort(+thingId),limit=(0,5)

Example 2

Report of all things which have been modified after January 21, 2019.
The result should contain the thing IDs, the revision number, and the timestamp of the latest modification.

 .../search/things?filter=gt(_modified,"2019-01-21")&fields=thingId,_revision,_modified

The search functionality is highly dedicated in updating its internal index as fast as possible. However, while working on distributed systems, beeing “eventually consistent” seems to fulfill the need of reaching a consistent state at some point in time.

The consistency should recover within milliseconds.