Read Objects
On this page
This page describes how to query and read objects from the a database with Atlas Device SDK. You can read the data that you have written to the database by finding, filtering, and sorting objects.
A read from the database generally consists of the following steps:
Get all objects of a certain type from the database instance.
Optionally, filter the results.
Optionally, sort the results.
The syntax for read operations is the same for synced and non-synced databases.
For information related to reading specific property types, including finding an object by primary key, refer to Read Properties.
Read Characteristics
Design your app's data access patterns around these read characteristics to read data as efficiently as possible.
SDK Results Collections
Results Are Not Copies
Unless you are working with frozen objects, results to a query are not copies of your data. Modifying the results of a query modifies the data on disk directly. This memory mapping also means that results are live: that is, they always reflect the current state on disk.
For more details about live versus frozen objects, refer to Live and Frozen Objects.
Results Are Lazy
The SDK only runs a query when you actually request the results of that query. This lazy evaluation enables you to write highly performant code for handling large data sets and complex queries. You can chain several filter operations without requiring extra work to process the intermediate state.
References Are Retained
Atlas Device SDK automatically retains all of an object's relationships as direct references. This enables you to traverse your graph of relationships directly through the results of a query.
A direct reference, or pointer, allows you to access a related object's properties directly through the reference.
Other databases typically copy objects from database storage into application memory when you need to work with them directly. Because application objects contain direct references, you are left with a choice: copy the object referred to by each direct reference out of the database in case it's needed, or copy the foreign key for each object and query for the object with that key if it's accessed. If you choose to copy referenced objects into application memory, you can use up a lot of resources for objects that are never accessed. If you copy only the foreign key, referenced object lookups can cause your application to slow down.
The SDK bypasses all of this using zero-copy live objects. Database object accessors point directly into database storage using memory mapping, so there is no distinction between the objects in the database and the results of your query in application memory. Because of this, you can traverse direct references across an entire database from any query result.
Limiting Query Results
As a result of lazy evaluation, you do not need any special mechanism to limit query results with the SDK. For example, if your query matches thousands of objects, but you only want to load the first ten, access only the first ten elements of the results collection. None of the remaining objects are loaded into memory.
Pagination
With lazy evaluation, pagination is very direct. Consider a query that matches thousands of objects in your realm. Your app displays one hundred objects per page. To advance to any page, access the elements of the results collection starting at the index that corresponds to the target page.
Read Database Objects
Read Object Methods
Read All Objects of a Type
Because results sets are homogenous by type, most read operations begin with querying for all objects of a type.
Filter or Query Objects
A filter selects a subset of results based on the value(s) of one or more object properties. The most common use case is to find objects where a certain property matches a certain value. Additionally, you can compare strings, aggregate over collections of numbers, and use logical operators to build up complex queries.
The SDK provides several full-featured query engines you can use to define filters. The core query engine uses Realm Query Language (RQL) to construct queries. RQL is a string-based query language that you can use to retrieve objects from the database. Some of the SDK languages provide special query APIs that provide idiomatic query syntax and features. The available query APIs include:
RQL: C++, C#, Dart, Java, JavaScript, Kotlin, TypeScript
LINQ: C#
Type-Safe and NSPredicate Queries: Swift, Objective-C
Fluent Interface: Java, Kotlin (Java SDK)
For more details about the supported operators when using each of these query APIs, refer to the query engine for your preferred language.
Tip
Filter on Related and Embedded Object Properties
To filter a query based on a property of an embedded object or a related object, use dot-notation as if it were in a regular, nested object.
Access Results
When you perform a read operation, such as getting all objects of a type or performing a query, the SDK returns a results collection that contains 0 or more objects.
The SDK provides convenience methods to make it easier to work with the results. The available methods vary depending on the SDK language.
Chain Queries
Because results are lazily evaluated, you can chain several queries together. Unlike traditional databases, this does not require a separate trip to the database for each successive query.
Sort
A sort operation allows you to configure the order in which the SDK returns queried objects. You can sort based on one or more properties of the objects in the results collection. The SDK only guarantees a consistent order of results if you explicitly sort them.
Tip
Sort on Related and Embedded Object Properties
To sort a query based on a property of an embedded object or a related object, use dot-notation as if it were in a regular, nested object.
Limit
SDK languages that use the Realm Query Language query engine can limit query results using the RQL LIMIT() operator.
Note that you can't use parameterized queries in RQL LIMIT() clauses. Instead, use strings or string interpolation.
Aggregate
You can aggregate results, which reduces results to a single value based on a specified numerical property or collection.
Section Query Results
Some of the SDK languages provide an API to split results collections into individual sections. Each section corresponds to a key generated from a property on the object it represents. This simplifies working with logical subsets of query results.
Query Projections
If your app defines a class projection to work with persisted data in a different way in a view model or based on certain business logic, you can query on that projection.
Tip
Don't do derived queries on top of class projection results. Instead, run a query against the SDK object directly and then project the result. If you try to do a derived query on top of class projection results, querying a field with the same name and type as the original object works, but querying a field with a name or type that isn't in the original object fails.