ObjectBox Queries

ObjectBox queries return persisted objects that match user defined criteria. With ObjectBox db you use the QueryBuilder class to specify criteria and create Query objects. The Query class will actually run the query and return matching objects.

QueryBuilder

The QueryBuilder<T> class lets you build custom queries for your entities. It is used along with the properties class generated for each entity.

This example assumes an entity class User and its generated properties class User_.

Simple condition example: Query for all users with the first name “Joe”:

Multiple conditions example: Get users with the first name “Joe” that are born later than 1970 and whose last name starts with “O”.

For an overview of all available criteria, please refer to the QueryBuilder class.

Query

Queries are created (and not yet executed) by calling build() on the QueryBuilder.

Finding objects

There are a couple of find methods to retrieve objects matching the query:

To return all entities matching the query simply call find().

To only return the first result, use findFirst().

If you expect a unique result call findUnique() instead. It will give you a single result or null, if no matching entity was found and throw an exception if there was more than one result.

Reusing Queries and Parameters

Query objects allow you to execute queries multiple times in an efficient way. To make queries more reusable all criteria values you previously set in the QueryBuilder can be changed. That’s why we call them query parameters.

Let’s look at an example:

Here we used one query object to find two sets of users, each with a specific first name. Note that we still have to initialize the value for the firstName property when building the query. Because we always overwrite the value using .setParameter()  we can just pass an empty string when initially building the query.

Caching the query object is good practice for queries that run frequently.

Limit, Offset, and Pagination

Sometimes you only need a subset of a query, for example the first 10 elements to display in your user interface. This is especially helpful (and resourceful) when you have a high number of entities and you cannot limit the result using query conditions only. The built Query<T> has a .find(long offset, long limit) method with offset and limit arguments:

offset: The first offset results are skipped.

limit: At most limit results of this query are returned.

Lazy loading results

To avoid loading query results right away, Query offers findLazy() and findLazyCached() which return a LazyList of the query results.

LazyList is a thread-safe, unmodifiable list that reads entities lazily only once they are accessed. Depending on the find method called, the lazy list will be cached or not. Cached lazy lists store the previously accessed objects to avoid loading entities more than once. Some features of the list are limited to cached lists (e.g. features that require the entire list). See the LazyList class documentation for more details.

 

PropertyQuery

If you only want to return the values of a certain property and not a list of full objects you can use a PropertyQuery. After building a query simply call property(Property)  to define the property followed by the appropriate find method.

For example to only get the email addresses of all users:

In general there is always a find method to return the value of the first result, or the values of all results. For example findString()  and findStrings()  and so on.

Note: an array of property values is not in any particular order, also not if you have set one when building the query.

Handling null values

By default null values are not returned. However, you can specify a replacement value to use if a property is null:

Distinct and unique results

The property query can also only return distinct values:

By default the case of strings is ignored. However, the distinct call can be overloaded to enable case sensitivity:

If only a single value is expected to be returned the query can be configured to throw if that is not the case:

The distinct and unique flags may also be combined.

Aggregating values

There are also useful methods to directly calculate the minimum, maximum, average and sum of all found values. See the PropertyQuery documentation for details.

 

Eager Loading of Relations

By default relations are loaded lazily: when you first access it it will perform a database lookup to get the data (subsequent accesses will get a cached values without). While this lookup is a fast operation with ObjectBox, there are situations in which you want to avoid this. ObjectBox also allows you to eagerly load relations to avoid those lookups completely. You can specify this using the QueryBuilder.eager() method.

 

Aggregates

Sometimes you do not want to return objects from a query, but get an aggregated value of a property. ObjectBox supports the following methods (each taking a property as parameter):

  • min / minDouble: Finds the minimum value for the given property over all objects matching the query.
  • max / maxDouble: Finds the maximum value.
  • sum / sumDouble : Calculates the sum of all values. Note: the non-double version detects overflows and throws an exception in that case.
  • avg : Calculates the average (always a double) of all values.

In addition, instead of getting the results themselves, you can get the number of results by calling count().

 

Removing Objects

To remove all objects matching a query, call query.remove() .

 

Spread the love