Navigation

Filter Data - Android SDK

The examples in this page use two Realm object types: Teacher and Student.

See the schema for these two classes below:

Teacher.kt
import io.realm.RealmList
import io.realm.RealmObject
open class Teacher : RealmObject() {
var name: String? = null
var numYearsTeaching: Int? = null
var subject: String? = null
var students: RealmList<Student>? = null
}
Student.kt
import io.realm.RealmObject
import io.realm.RealmResults
import io.realm.annotations.LinkingObjects
open class Student : RealmObject() {
var name: String? = null
var year: Int? = null
@LinkingObjects("students")
val teacher: RealmResults<Teacher>? = null
}

You can build filters using the operator methods of the fluent interface exposed by the RealmQuery class:

// Build the query looking at all teachers:
val query = realm.where(Teacher::class.java)
// Add query conditions:
query.equalTo("name", "Ms. Langtree")
query.or().equalTo("name", "Mrs. Jacobs")
// Execute the query:
val result1 = query.findAll()
// Or alternatively do the same all at once (the "Fluent interface"):
val result2 = realm.where(Teacher::class.java)
.equalTo("name", "Ms. Langtree")
.or()
.equalTo("name", "Mrs. Jacobs")
.findAll()

This gives you a new instance of the class RealmResults, containing teachers with the name "Ms. Langtree" or "Mrs. Jacobs".

RealmQuery includes several methods that can execute queries:

  • findAll() blocks until it finds all objects that meet the query conditions
  • findAllAsync() returns immediately and finds all objects that meet the query conditions asynchronously on a background thread
  • findFirst() blocks until it finds the first object that meets the query conditions
  • findFirstAsync() returns immediately and finds the first object that meets the query conditions asynchronously on a background thread

Queries return a list of references to the matching Realm objects using the RealmResults type.

Tip
See also:

When referring to an object property, you can use dot notation to refer to child properties of that object. You can refer to the properties of embedded objects and relationships with dot notation.

For example, consider a query for all teachers with a student named "Wirt" or "Greg":

// Find all teachers who have students with the names "Wirt" or "Greg"
val result = realm.where(Teacher::class.java)
.equalTo("students.name", "Wirt")
.or()
.equalTo("students.name", "Greg")
.findAll()

You can even use dot notation to query inverse relationships:

// Find all students who have teachers with the names "Ms. Langtree" or "Mrs. Jacobs"
val result = realm.where(Student::class.java)
.equalTo("teacher.name", "Ms. Langtree")
.or()
.equalTo("teacher.name", "Mrs. Jacobs")
.findAll()

You can define the order of query results using the sort() method:

// Find all students in year 7, and sort them by name
val result: RealmResults<Student> = realm.where(Student::class.java)
.equalTo("year", 7L)
.sort("name")
.findAll()
// Alternatively, find all students in year 7
val unsortedResult: RealmResults<Student> = realm.where(Student::class.java)
.equalTo("year", 7L)
.findAll()
// then sort the results set by name
val sortedResult = unsortedResult.sort("name")

Sorts organize results in ascending order by default. To organize results in descending order, pass Sort.DESCENDING as a second argument. You can resolve sort order ties between identical property values by passing an array of properties instead of a single property: in the event of a tie, Realm Database sorts the tied objects by subsequent properties in order.

Important

Realm Database applies the distinct(), sort() and limit() methods in the order you specify. Depending on the data set this can alter the query result. Generally, you should apply limit() last to avoid unintended result sets.

Important
String Sorting Limitations

Realm uses non-standard sorting for upper and lowercase letters, sorting them together rather than sorting uppercase first. As a result, '- !"#0&()*,./:;?_+<=>123aAbBcC...xXyYzZ is the actual sorting order in Realm Database. Additionally, sorting strings only supports the Latin Basic, Latin Supplement, Latin Extended A, and Latin Extended B (UTF-8 range 0–591) character sets.

You can cap the number of query results to a specific maximum number using the limit() method:

// Find all students in year 8, and limit the results collection to 10 items
val result: RealmResults<Student> = realm.where(Student::class.java)
.equalTo("year", 8L)
.limit(10)
.findAll()

Limited result collections automatically update like any other query result. Consequently, objects might drop out of the collection as underlying data changes.

Important
Pagination is Not Necessary for Realm Database Optimization

Some databases encourage paginating results with limits to avoid reading unnecessary data from disk or using too much memory.

Since Realm Database queries are lazy, there is no need to take such measures. Realm Database only loads objects from query results when they are explicitly accessed.

Warning
Deleted Notifications in Limited Results

Collection notifications report objects as deleted when they drop out of the result set. This does not necessarily mean that they have been deleted from the underlying realm, just that they are no longer part of the query result.

You can reduce query results to unique values for a given field or fields using the distinct() method:

// Find all students in year 9, and cap the result collection at 10 items
val result: RealmResults<Student> = realm.where<Student>(Student::class.java)
.equalTo("year", 9L)
.distinct("name")
.findAll()

You can only call distinct() on integer, long, short, and String fields; other field types will throw an exception. As with sorting, you can specify multiple fields to resolve ties.

You can apply additional filters to a results collection by calling the where() method:

// Find all students in year 9 and resolve the query into a results collection
val result: RealmResults<Student> = realm.where(Student::class.java)
.equalTo("year", 9L)
.findAll()
// filter the students results again by teacher name
val filteredResults =
result.where().equalTo("teacher.name", "Ms. Langtree").findAll()

The where() method returns a RealmQuery that you can resolve into a RealmResults using a find method. Filtered results can only return objects of the same type as the original results set, but are otherwise able to use any filters.

New in version 10.4.0.

You can use RealmQuery.rawPredicate() to query realms using Realm Query Language, a language inspired by NSPredicate. Realm Query Language can use either the class and property names defined in your Realm Model classes or the internal names defined with @RealmField. You can combine raw predicates with other raw predicates or type-safe predicates created with RealmQuery:

// Build a RealmQuery based on the Student type
val query = realm.where(Student::class.java)
// Simple query
val studentsNamedJane = query.rawPredicate("name = 'Jane'").findAll()
// Multiple predicates
val studentsNamedJaneOrJohn =
query.rawPredicate("name = 'Jane' OR name = 'John'").findAll()
// Collection queries
val studentsWithTeachers =
query.rawPredicate("teacher.@count > 0").findAll()
val studentsWithSeniorTeachers =
query.rawPredicate("ALL teacher.numYearsTeaching > 5").findAll()
// Sub queries
val studentsWithMathTeachersNamedSteven =
query.rawPredicate("SUBQUERY(teacher, \$teacher, \$teacher.subject = 'Mathematics' AND \$teacher.name = 'Mr. Stevens').@count > 0")
.findAll()
// Sort, Distinct, Limit
val students =
query.rawPredicate("teacher.@count > 0 SORT(year ASCENDING) DISTINCT(name) LIMIT(5)")
.findAll()
// Combine two raw predicates
val studentsNamedJaneOrHenry = query.rawPredicate("name = 'Jane'")
.rawPredicate("name = 'Henry'").findAll()
// Combine raw predicate with type-safe predicate
val studentsNamedJaneOrHenryAgain =
query.rawPredicate("name = 'Jane'")
.equalTo("name", "Henry").findAll()
Tip
See also:

For more information about Realm Query Language, see the iOS query examples and the Node.js query engine reference.

Give Feedback