Docs Menu

Filter Data - Swift SDKicons/link.png

On this page

To filter data in your realm, you can leverage Realm Database's query engine.

New in version 10.19.0:: Realm Swift Query API

The Realm Swift Query API offers an idiomatic way for Swift developers to query data. Use Swift-style syntax to query Realm Database with the benefits of auto-completion and type safety. The Realm Swift Query API does not replace the NSPredicate Query API in newer SDK versions; instead, you can use either.

For SDK versions prior to 10.19.0, or for Objective-C developers, Realm Database's query engine supports NSPredicate Query.

The examples in this page use a simple data set for a task list app. The two Realm object types are Project and Task. A Task has a name, assignee's name, and completed flag. There is also an arbitrary number for priority -- higher is more important -- and a count of minutes spent working on it. A Project has zero or more Tasks.

See the schema for these two classes, Project and Task, below:

You can set up the realm for these examples with the following code:

New in version 10.19.0: For SDK versions older than 10.19.0, use the NSPredicate query API.

You can build a filter with Swift-style syntax using the .where Realm Swift query API:

let realmSwiftQuery = projects.where {
($0.tasks.progressMinutes > 1) && ($0.tasks.assignee == "Ali")
}

This query API constructs an NSPredicate to perform the query. It gives developers a type-safe idiomatic API to use directly, and abstracts away the NSPredicate construction.

The .where API takes a callback that evaluates to true or false. The callback receives an instance of the type being queried, and you can leverage the compiler to statically check that you are creating valid queries that reference valid properties.

In the examples on this page, we use the $0 shorthand to reference the variable passed into the callback.

You can iterate through a collection property with another query using a subquery. To form a subquery, you must wrap the expression in parenthesis and immediately follow it with the .count aggregator.

(<query>).count > n

If the expression does not produce a valid subquery, you’ll get an exception at runtime.

Example

Running the following query on a projects collection returns projects with tasks that have not been completed by a user named Alex.

let subquery = projects.where {
($0.tasks.isComplete == false && $0.tasks.assignee == "Alex").count > 0
}
print("Projects with incomplete tasks assigned to Alex: \(subquery.count)")

There are several types of operators available to query a Realm collection. Queries work by evaluating an operator expression for every object in the collection being queried. If the expression resolves to true, Realm Database includes the object in the results collection.

You can use Swift comparison operators with the Realm Swift Query API (==, !=, >, >=, <, <=).

Example

The following example uses the query engine's comparison operators to:

  • Find high priority tasks by comparing the value of the priority property value with a threshold number, above which priority can be considered high.
  • Find long-running tasks by seeing if the progressMinutes property is at or above a certain value.
  • Find unassigned tasks by finding tasks where the assignee property is equal to null.
let highPriorityTasks = tasks.where {
$0.priority > 5
}
print("High-priority tasks: \(highPriorityTasks.count)")
let longRunningTasks = tasks.where {
$0.progressMinutes >= 120
}
print("Long running tasks: \(longRunningTasks.count)")
let unassignedTasks = tasks.where {
$0.assignee == nil
}
print("Unassigned tasks: \(unassignedTasks.count)")

You can query for values within a collection using the .contains operators. You can search for individual values by element, or search within a range.

Operator
Description
.contains(_ element:)
Equivalent to the IN operator. Evaluates to true if the property referenced by the expression contains the value.
.contains(_ range:)
Equivalent to the BETWEEN operator. Evaluates to true if the property referenced by the expression contains a value that is within the range.
Example
  • Find tasks assigned to specific teammates Ali or Jamie by seeing if the assignee property is in a list of names.
  • Find tasks where the progressMinutes property is within a given range of minutes.
let aliOrJamiesTasks = tasks.where {
$0.assignee.contains("Ali") || $0.assignee.contains("Jamie")
}
print("Tasks IN Ali or Jamie: \(aliOrJamiesTasks.count)")
let progressBetween30and60 = tasks.where {
$0.progressMinutes.contains(30...60)
}
print("Tasks with progress between 30 and 60 minutes: \(progressBetween30and60.count)")

You can make compound queries using Swift logical operators (&&, !, ||).

Example

We can use the query language's logical operators to find all of Ali's completed tasks. That is, we find all tasks where the assignee property value is equal to 'Ali' AND the isComplete property value is true:

let aliComplete = tasks.where {
($0.assignee == "Ali") && ($0.isComplete == true)
}
print("Ali's complete tasks: \(aliComplete.count)")

You can compare string values using these string operators. Regex-like wildcards allow more flexibility in search.

Note

You can use the following options with string operators:

  • .caseInsensitive for case insensitivity.

    $0.name.contains("f", options: .caseInsensitive)
  • .diacriticInsensitive for diacritic insensitivity: Realm treats special characters as the base character (e.g. é -> e).

    $0.name.contains("e", options: .diacriticInsensitive)
Operator
Description
.starts(with value: String)
Evaluates to true if the collection contains an element whose value begins with the specified string value.
.contains(_ value: String)
Evaluates to true if the left-hand string expression is found anywhere in the right-hand string expression.
.ends(with value: String)
Evaluates to true if the collection contains an element whose value ends with the specified string value.
.like(_ value: String)

Evaluates to true if the left-hand string expression matches the right-hand string wildcard string expression. A wildcard string expression is a string that uses normal characters with two special wildcard characters:

  • The * wildcard matches zero or more of any character
  • The ? wildcard matches any character.

For example, the wildcard string "d?g" matches "dog", "dig", and "dug", but not "ding", "dg", or "a dog".

==
Evaluates to true if the left-hand string is lexicographically equal to the right-hand string.
!=
Evaluates to true if the left-hand string is not lexicographically equal to the right-hand string.
Example

The following example uses the query engine's string operators to find:

  • Projects with a name starting with the letter 'e'
  • Projects with names that contain 'ie'
  • Projects with an assignee property whose value is similar to Al?x
  • Projects that contain e-like characters with diacritic insensitivity
// Use the .caseInsensitive option for case-insensitivity.
let startWithE = projects.where {
$0.name.starts(with: "e", options: .caseInsensitive)
}
print("Projects that start with 'e': \(startWithE.count)")
let containIe = projects.where {
$0.name.contains("ie")
}
print("Projects that contain 'ie': \(containIe.count)")
let likeWildcard = tasks.where {
$0.assignee.like("Al?x")
}
print("Tasks with assignees like Al?x: \(likeWildcard.count)")
// Use the .diacreticInsensitive option for diacritic insensitivty: contains 'e', 'E', 'é', etc.
let containElike = projects.where {
$0.name.contains("e", options: .diacriticInsensitive)
}
print("Projects that contain 'e', 'E', 'é', etc.: \(containElike.count)")
Note

String sorting and case-insensitive queries are only supported for character sets in 'Latin Basic', 'Latin Supplement', 'Latin Extended A', and 'Latin Extended B' (UTF-8 range 0-591).

You can apply an aggregate operator to a collection property of a Realm object. Aggregate operators traverse a collection and reduce it to a single value.

Operator
Description
.avg
Evaluates to the average value of a given numerical property across a collection.
.count
Evaluates to the number of objects in the given collection. This is currently only supported on to-many relationship collections and not on lists of primitives. In order to use .count on a list of primitives, consider wrapping the primitives in a Realm object.
.max
Evaluates to the highest value of a given numerical property across a collection.
.min
Evaluates to the lowest value of a given numerical property across a collection.
.sum
Evaluates to the sum of a given numerical property across a collection.
Example

We create a couple of filters to show different facets of the data:

  • Projects with average tasks priority above 5.
  • Projects that contain only low-priority tasks below 5.
  • Projects where all tasks are high-priority above 5.
  • Projects that contain more than 5 tasks.
  • Long running projects.
let averageTaskPriorityAbove5 = projects.where {
$0.tasks.priority.avg > 5
}
print("Projects with average task priority above 5: \(averageTaskPriorityAbove5.count)")
let allTasksLowerPriority = projects.where {
$0.tasks.priority.max < 5
}
print("Projects where all tasks are lower priority: \(allTasksLowerPriority.count)")
let allTasksHighPriority = projects.where {
$0.tasks.priority.min > 5
}
print("Projects where all tasks are high priority: \(allTasksHighPriority.count)")
let moreThan5Tasks = projects.where {
$0.tasks.count > 5
}
print("Projects with more than 5 tasks: \(moreThan5Tasks.count)")
let longRunningProjects = projects.where {
$0.tasks.progressMinutes.sum > 100
}
print("Long running projects: \(longRunningProjects.count)")

The NSPredicate Query API supports using set operators to evaluate objects in a collection: ALL, ANY/SOME, NONE.

These set operators use specific rules to determine whether to pass each input collection object to the output collection by applying a given query expression to every element of a given list property of the object.

The Realm Swift Query API does not explicitly support these set operators. If you need to explicitly use any of these set operators in your filters, use the NSPredicate Query API with set operators.

You can build a filter with NSPredicate:

Filters consist of expressions in an NSPredicate. An expression consists of one of the following:

  • The name (keypath) of a property of the object currently being evaluated.
  • An operator and up to two argument expression(s).
  • A value, such as a string ('hello') or a number (5).

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

For example, consider a query on an object with a workplace property that refers to a Workplace object. The Workplace object has an embedded object property, address. You can chain dot notations to refer to the zipcode property of that address:

workplace.address.zipcode == 10012

You can use the following substitutions in your predicate format strings:

  • %@ to specify values
  • %K to specify keypaths

You can iterate through a collection property with another query using the SUBQUERY() predicate function. SUBQUERY() has the following signature:

SUBQUERY(<collection>, <variableName>, <predicate>)
  • collection: the name of the list property to iterate through
  • variableName: a variable name of the current element to use in the subquery
  • predicate: a string that contains the subquery predicate. You can use the variable name specified by variableName to refer to the currently-iterated element.
Example

Running the following filter on a projects collection returns projects with tasks that have not been completed by a user named Alex.

There are several types of operators available to filter a Realm collection. Filters work by evaluating an operator expression for every object in the collection being filtered. If the expression resolves to true, Realm Database includes the object in the results collection.

The most straightforward operation in a search is to compare values.

Important
Types Must Match

The type on both sides of the operator must be equivalent. For example, comparing an ObjectId with string will result in a precondition failure with a message like:

"Expected object of type object id for property 'id' on object of type
'User', but received: 11223344556677889900aabb (Invalid value)"

You can compare any numeric type with any other numeric type.

Operator
Description
between
Evaluates to true if the left-hand numerical or date expression is between or equal to the right-hand range. For dates, this evaluates to true if the left-hand date is within the right-hand date range.
==, =
Evaluates to true if the left-hand expression is equal to the right-hand expression.
>
Evaluates to true if the left-hand numerical or date expression is greater than the right-hand numerical or date expression. For dates, this evaluates to true if the left-hand date is later than the right-hand date.
>=
Evaluates to true if the left-hand numerical or date expression is greater than or equal to the right-hand numerical or date expression. For dates, this evaluates to true if the left-hand date is later than or the same as the right-hand date.
in
Evaluates to true if the left-hand expression is in the right-hand list or string.
<
Evaluates to true if the left-hand numerical or date expression is less than the right-hand numerical or date expression. For dates, this evaluates to true if the left-hand date is earlier than the right-hand date.
<=
Evaluates to true if the left-hand numeric expression is less than or equal to the right-hand numeric expression. For dates, this evaluates to true if the left-hand date is earlier than or the same as the right-hand date.
!=, <>
Evaluates to true if the left-hand expression is not equal to the right-hand expression.
Example

The following example uses the query engine's comparison operators to:

  • Find high priority tasks by comparing the value of the priority property value with a threshold number, above which priority can be considered high.
  • Find long-running tasks by seeing if the progressMinutes property is at or above a certain value.
  • Find unassigned tasks by finding tasks where the assignee property is equal to null.
  • Find tasks assigned to specific teammates Ali or Jamie by seeing if the assignee property is in a list of names.

You can make compound predicates using logical operators.

Operator
Description
and
&&
Evaluates to true if both left-hand and right-hand expressions are true.
not
!
Negates the result of the given expression.
or
||
Evaluates to true if either expression returns true.
Example

We can use the query language's logical operators to find all of Ali's completed tasks. That is, we find all tasks where the assignee property value is equal to 'Ali' AND the isComplete property value is true:

You can compare string values using these string operators. Regex-like wildcards allow more flexibility in search.

Note

You can use the following modifiers with the string operators:

  • [c] for case insensitivity.

  • [d] for diacritic insensitivity: Realm treats special characters as the base character (e.g. é -> e).

Operator
Description
beginsWith
Evaluates to true if the left-hand string expression begins with the right-hand string expression. This is similar to contains, but only matches if the right-hand string expression is found at the beginning of the left-hand string expression.
contains, in
Evaluates to true if the left-hand string expression is found anywhere in the right-hand string expression.
endsWith
Evaluates to true if the left-hand string expression ends with the right-hand string expression. This is similar to contains, but only matches if the left-hand string expression is found at the very end of the right-hand string expression.
like

Evaluates to true if the left-hand string expression matches the right-hand string wildcard string expression. A wildcard string expression is a string that uses normal characters with two special wildcard characters:

  • The * wildcard matches zero or more of any character
  • The ? wildcard matches any character.

For example, the wildcard string "d?g" matches "dog", "dig", and "dug", but not "ding", "dg", or "a dog".

==, =
Evaluates to true if the left-hand string is lexicographically equal to the right-hand string.
!=, <>
Evaluates to true if the left-hand string is not lexicographically equal to the right-hand string.
Example

We use the query engine's string operators to find projects with a name starting with the letter 'e' and projects with names that contain 'ie':

Note

String sorting and case-insensitive queries are only supported for character sets in 'Latin Basic', 'Latin Supplement', 'Latin Extended A', and 'Latin Extended B' (UTF-8 range 0-591).

You can apply an aggregate operator to a collection property of a Realm object. Aggregate operators traverse a collection and reduce it to a single value.

Operator
Description
@avg
Evaluates to the average value of a given numerical property across a collection.
@count
Evaluates to the number of objects in the given collection. This is currently only supported on to-many relationship collections and not on lists of primitives. In order to use @count on a list of primitives, consider wrapping the primitives in a Realm object.
@max
Evaluates to the highest value of a given numerical property across a collection.
@min
Evaluates to the lowest value of a given numerical property across a collection.
@sum
Evaluates to the sum of a given numerical property across a collection.
Example

We create a couple of filters to show different facets of the data:

  • Projects with average tasks priority above 5.
  • Long running projects.

A set operator uses specific rules to determine whether to pass each input collection object to the output collection by applying a given predicate to every element of a given list property of the object.

Operator
Description
ALL
Returns objects where the predicate evaluates to true for all objects in the collection.
ANY, SOME
Returns objects where the predicate evaluates to true for any objects in the collection.
NONE
Returns objects where the predicate evaluates to false for all objects in the collection.
Example

We use the query engine's set operators to find:

  • Projects with no complete tasks.
  • Projects with any top priority tasks.
Give Feedback
MongoDB logo
© 2021 MongoDB, Inc.

About

  • Careers
  • Investor Relations
  • Legal Notices
  • Privacy Notices
  • Security Information
  • Trust Center
© 2021 MongoDB, Inc.