How we use OData

Power of the data at your fingertips

OData is an open standard for accessing and working with data in Web APIs. You can read about the standard on the OData Site

A brief introduction to how Flex uses OData

Most services in Flex adopt the OASIS OData standard for interrogation (and editing)

This provides a consistent, convention driven means of accessing data, and self-describing schema that permits 3rd party tools to dynamically discover the schema and assist users in querying records.

Examples of tools that support OData querying include, Microsoft Excel, PowerBI and much of the Office 365 eco-system - meaning Flex can integrate with these tools out the box.

All the core OData features are advertised through the OpenAPI interface. However, some features do require knowledge of the OData syntax to utilise the full functionality.

At its simplest OData can be considered SQL over HTTP, permitting a structured query language for accessing data over the internet.

OData Querying

Building OData queries is a matter of setting options on the Query String. If using a generated client from our OpenAPI these query-string parameters are available as properties that can be populated according to the OData conventions.

Basic Use-cases

OData provides the fundamental ability to select, filter, order, and page data from the data source. It also support more advanced concepts such as expansion (similar to a Join in SQL), and aggregation.

Select / Projection : $select

In order to reduce the amount of data queried and delivered (reducing internet payloads and server processing) use of the $select parameter allows consumers to define the fields required.

Field name are currently case-sensitive

Omitting a $select returns all fields is the SQL equivalent of ‘Select * from …

Filtering; $filter

The $filter operation is used apply filtering to a data set – in a similar means to a WHERE clause in SQL.

Filtering supports a sophisticated grammar supporting operators such as

OperatorDescription
eqEquals
neNot Equals
ltLess than
gtGreater than
leLess than or equal
geGreater than or equal
anyWhere any child item matches some criteria
allWhere all child items match some criteria
andWhere all conditions apply
orWhere any of the conditions apply
notUsed to negate a condition
hasBitwise filtering of enum flags

For a general introduction see https://www.odata.org/getting-started/basic-tutorial/

For more in depth details see http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part2-url-conventions/odata-v4.0-errata03-os-part2-url-conventions-complete.html#_Toc453752358

Filtering also support a number of built-in functions including:

FunctionDescription
contains()To test if a text value contains some value
startswith()To test if a text value starts with some value
endswith()To test if a text value ends with some value
toupper()Convert the text to upper case
tolower()Convert the text to lower case
[other date and math operators]See OData Docs

Paging : $top, $skip

Paging allows large data sets to be sent and displayed in the client application in defined windows.

Odata allows the page size to be set with the $top operator. Pages can be navigated to using the $skip operator to skip over the appropriate number of records.

A sort order should be provided when paging.

If unspecified, the default page size is 1000 records.

For performance reasons the maximum page size is 1000 records. Larger data sets can be access using multiple queries and use of the $skip operator

Count; $count

Because of paging, the number of results returned may be less than the overall set of matching result.

To implement paging controls, and provide feedback to the end user, it’s useful to know how many records match a query in total. The $count operator when enabled returns the overall count of matching entities as part of the results.

This can be used to calculate the number of pages, and provide navigation through the results

Sorting: $orderby

Most properties can be used for sorting a result set, using the $orderby operator. Columns can be sorted by ascending and descending order.

Composite Sorting can be by providing multiple fields - comma separated.

🚧

When no sort is defined the sequence may be undefined and unstable.

Setting a $orderby value will guarantee consistent results

Navigation/Expansion: $expand

Expansion allows related resources to be included in the results. It’s loosely analogous to a JOIN in SQL.

Using the $expand operator enables a parent entity or a collection of child entities to be included in the results in a single query -which is much more efficient than making multiple queries.

E.g.

👍

Example Navigation use cases

Find all Spaces and include their Components

Find all Zones including the top 10 Spaces that

When expanding collections those child collections can also have $select, $filter, $orderby, $top, $skip and $count operators applied to precisely define & limit the result set.

You can additionally expand child items (but be careful not to overload the system with excessively large data sets)

E.g.

👍

Find all Components , including the Spaces they are in and the Floor they belong to

/Components?$filter=<somefilter>&$expand=Spaces($expand=Level) 

Advanced Querying

Portfolio level querying

The default querying in the Flex Aim model is at “portfolio level” – i.e across all visible assets and models.

If no filter is provided the results will be of all entities in models where the current user has access to see in the current tenant (based on permissions). That permits conceptual queries such as

‘Find all spaces across all my assets with a classification of SL_20_15_50 : Meeting rooms and an Occupancy > 10’

More typically additional filtering will be employed to limit results from a specific model, or set of models under an asset. E.g.

Spaces?$filter=AssetModelId eq 1234 
# All rooms in Model 1234

Spaces?$filter=Model/AssetId eq 5678 and Model/IsCurrent eq true and Model/SegmentName eq “Architecture”&$expand=Model 
#All rooms in the latest “Architectural” models linked to Asset 5678

Advanced Filtering

The OData query system provides some very sophisticated querying, especially when utilising the $expands capabilities. A few examples include:

Find all Windows that don’t have a Type associated

Find all Spaces where no Components classified as Pr_40_50_28 : Extinguishers

Find all Doors that don’t have a Fire-Rating defined

Aggregates

OData supports grouping and aggregation, enabling consumers to use the server to calculate totals, sums and averages (etc) of values without downloading all the data. E.g.

Find the total Area of all Rooms on the 3rd Floor.

Find all duplicate named Component types in a model (in thise case we are both aggregating and filtering on the aggregate result)

ComponentTypes?$apply=filter(AssetModelId eq 1234)/groupby((Name), aggregate($count as Count))&$filter=Count gt 1


What’s Next