---
title: Filtering and Sorting Expressions
slug: develop/filtering-and-sorting-expressions
docTags: 
createdAt: 2025-03-11T07:03:28.938Z
---

This page describes filtering and sorting expressions in the Main API.

## Filtering and Sorting Expressions 

This example describes the player entity, but the same solution is implemented for all other entities (for example, groups, feeds, playlists, etc.). 

### Example

The BSN.Cloud Main API currently exposes the following player management methods which accept optional filter and sort expressions:

:::BlockQuote
GET \~/\{\{version}}/REST/Devices/\[?marker=\{string}]\[\&pageSize=\{byte}]\[\&filter=\{expression}]\[\&sort=\{expression}]
:::

which retrieves the paged list including up to 100 'Device' instances starting from the specified marker, matching the specified filter expression and sorted in accordance to the specified sort expression.

:::BlockQuote
GET \~/\{\{version}}/REST/Devices/Regions/\{\*locationPath}/\[?filter=\{expression}]
:::

which retrieves the list of 'DevicesRegion' providing the aggregated information of locations of 'Device' instances matching the specified location path and filter expression.

:::BlockQuote
GET \~/\{\{version}}/REST/Devices/Count/\[?filter=\{expression}]
:::

which retrieves the number of 'Device' instances matching the specified filter expression.

:::BlockQuote
PATCH \~/\{\{version}}/REST/Devices/\[?filter=\{expression}]
:::

(in development) which applies the specified changes to 'Device' instances matching the specified filter expression.

:::BlockQuote
DELETE \~/\{\{version}}/REST/Devices/\[?filter=\{expression}]
:::

which deletes the 'Device' instances matching the specified filter expression.

## Filter Expression Criteria

- Each filter expression may contain one or more criteria combined by AND/OR operators and optionally grouped by parentheses.
- Each criteria may be based on property name, system tag, or custom tag.
- All property names are based on data contract of the target Main API version

## System and Custom Tags

In addition to properties each 'Player' entity instance may have a different set of system and custom tags specified by customer, exposed via the `[Dictionary<string, object>] Tags` property and managed via the following BSN.Cloud Main API methods:

:::BlockQuote
PUT \~/\{version}/REST/Devices/\{playerId\:int}/
:::

:::BlockQuote
PUT \~/\{version}/REST/Devices/\{serial}/
:::

:::BlockQuote
PATCH \~/\{version}/REST/Devices/\{playerId\:int}/
:::

:::BlockQuote
PATCH \~/\{version}/REST/Devices/\{serial}/
:::

:::BlockQuote
GET \~/\{version}/REST/Devices/\{playerId\:int}/Tags/
:::

:::BlockQuote
GET \~/\{version}/REST/Devices/\{serial}/Tags/
:::

:::BlockQuote
POST \~/\{version}/REST/Devices/\{playerId\:int}/Tags/
:::

:::BlockQuote
POST \~/\{version}/REST/Devices/\{serial}/Tags/
:::

:::BlockQuote
DELETE \~/\{version}/REST/Devices/\{playerId\:int}/Tags/
:::

:::BlockQuote
DELETE \~/\{version}/REST/Devices/\{serial}/Tags/
:::

Each system and custom tag must be explicitly specified for the target entity instance but the list of available system tags is predefined by product owners and mapped to some properties so their values must be always in sync. For example, the system tag mapped to the Player Health Status property is called:

`string::[Device].<HealthStatus>`

## Property and Tag Mentions in Expressions

Property and tag mentions in expressions are different: properties are wrapped by square brackets and are separated by dots while tags are wrapped by angle brackets and may optionally be prepended by the target entity name in square brackets, and the data type is separated by double colon as you can see in the example above. Each property and tag has a strong data type, for properties and system tags it is defined in data contract of a target API version and for custom tags it is resolved either from fully qualified name or first assigned value. In addition, there is a request to support custom tags without values acting as labels. The data type defines which operators and functions are applicable to a given property or tag in conditions.

The properties and tags of **boolean** data type typically support the following operators:

:::BlockQuote
IS TRUE
:::

:::BlockQuote
IS FALSE
:::

The properties and tags of **numeric** data types typically support the following operators:

:::BlockQuote
IS \{number}
:::

:::BlockQuote
IS NOT \{number}
:::

:::BlockQuote
IS GREATER THAN \{number}
:::

:::BlockQuote
IS LESS THAN \{number}
:::

:::BlockQuote
IS IN THE RANGE \{number} AND \{number}
:::

:::BlockQuote
IS NOT IN THE RANGE \{number} AND \{number}
:::

:::BlockQuote
IS IN (\{number}, \{number}, ...)
:::

:::BlockQuote
IS NOT IN (\{number}, \{number}, ...)
:::

The GPS coordinates also support expressions like:

:::BlockQuote
GPS LOCATION (\[Latitude] AND \[Longitude]) IN (\{latitude}, \{longitude}, \{distance})
:::

:::BlockQuote
GPS LOCATION (\[Latitude] AND \[Longitude]) NOT IN (\{latitude}, \{longitude}, \{distance})
:::

The properties and tags of **string** data type typically support the following operators:

:::BlockQuote
IS NULL
:::

:::BlockQuote
IS NOT NULL
:::

:::BlockQuote
IS '\{expression}'
:::

:::BlockQuote
IS NOT '\{expression}'
:::

:::BlockQuote
BEGINS WITH '\{string}'
:::

:::BlockQuote
ENDS WITH '\{string}'
:::

:::BlockQuote
CONTAINS '\{string}'
:::

:::BlockQuote
DOES NOT CONTAIN '\{string}'
:::

:::BlockQuote
CONTAINS ALL ('\{string}', '\{string}', ...)
:::

:::BlockQuote
CONTAINS ANY ('\{string}', '\{string}', ...)
:::

:::BlockQuote
IS IN ('\{string}', '\{string}', ...)
:::

:::BlockQuote
IS NOT IN ('\{string}', '\{string}', ...)
:::

The expressions used in IS and IS NOT operators may include '\*', '?', '\[' + ']' wildcards.

The properties and tags of **DateTime** (timestamp) data type typically support the following operators:

:::BlockQuote
IS '\{DateTime}'
:::

:::BlockQuote
IS NOT '\{DateTime}'
:::

:::BlockQuote
IS AFTER '\{DateTime}'
:::

:::BlockQuote
IS BEFORE '\{DateTime}'
:::

:::BlockQuote
IN THE LAST (\{interval}, \{range}, '\{DateTime}')&#x20;
:::

where \{interval} is one of \{ "YEARS", "MONTHS", "DAYS" } enumeration values

:::BlockQuote
NOT IN THE LAST (\{interval}, \{range}, '\{DateTime}')&#x20;
:::

where \{interval} is one of \{ "YEARS", "MONTHS", "DAYS" } enumeration values

:::BlockQuote
IS IN THE RANGE '\{DateTime}' AND '\{DateTime}'
:::

:::BlockQuote
IS NOT IN THE RANGE '\{DateTime}' AND '\{DateTime}'
:::

:::BlockQuote
IS IN ('\{DateTime}', '\{DateTime}')
:::

:::BlockQuote
IS NOT IN ('\{DateTime}', '\{DateTime}')
:::

The '\{DateTime}' value format must follow ISO 8601 and is typically like '2021-12-20T18:25:01.123Z'.

The properties and tags of **TimeSpan** (time interval) data type typically support the following operators:

:::BlockQuote
IS '\{TimeSpan}'
:::

:::BlockQuote
IS NOT '\{TimeSpan}'
:::

:::BlockQuote
IS GREATER THAN '\{TimeSpan}'
:::

:::BlockQuote
IS LESS THAN '\{TimeSpan}'
:::

:::BlockQuote
IS IN ('\{TimeSpan}', '\{TimeSpan}')
:::

:::BlockQuote
IS NOT IN ('\{TimeSpan}', '\{TimeSpan}')
:::

The '\{TimeSpan}' value format must follow ISO 8601 and is typically like '3.18:25:01'.

The properties and tags of **numeric array** data types typically support the following operators:

:::BlockQuote
IS NULL
:::

:::BlockQuote
IS NOT NULL
:::

:::BlockQuote
CONTAINS ALL ('\{number}', '\{number}', ...)
:::

:::BlockQuote
CONTAINS ANY ('\{number}', '\{number}', ...)
:::

The properties and tags of **string array** data type typically support the following operators:

:::BlockQuote
IS NULL
:::

:::BlockQuote
IS NOT NULL
:::

:::BlockQuote
CONTAINS ALL ('\{string}', '\{string}', ...)
:::

:::BlockQuote
CONTAINS ANY ('\{string}', '\{string}', ...)
:::

The properties and tags of **object** data type typically support the following operators:

:::BlockQuote
IS NULL
:::

:::BlockQuote
IS NOT NULL
:::

Sort expressions may contain only one fully qualified property name or tag with optional ASC/DESC qualifier, but should support more in future.
