Docs Menu

Docs HomeRealm

Read Realm Objects - Kotlin SDK

On this page

  • Find Objects
  • Find Object by Primary Key
  • Find Objects of a Type
  • Query an Embedded Object
  • Query a Dictionary Property
  • Query a RealmSet Property
  • Filter Data
  • Filter Results
  • Filter with Full-Text Search
  • Sort Results
  • Iterate Results

Tip

find() is Synchronous

find() runs a synchronous query on the thread it is called from. As a result, avoid using find() on the UI thread or in logic that could delay the UI thread.

Prefer asFlow() in time-sensitive environments.

To find an object with a specific primary key value, open a realm and query the primary key field for the desired primary key value using realm.query(). Specify the object type as a type parameter passed to query():

// Search equality on the primary key field name
val frogs: Frog? = realm.query<Frog>("_id == $0", PRIMARY_KEY_VALUE).first().find()

To find all objects of a type, open a realm and pass the type as a type parameter to realm.query():

// fetch all objects of a type as a flow, asynchronously
val frogsFlow: Flow<ResultsChange<Frog>> = realm.query<Frog>().asFlow()
val asyncCall: Deferred<Unit> = async {
frogsFlow.collect { results ->
when (results) {
// print out initial results
is InitialResults<Frog> -> {
for (frog in results.list) {
Log.v("Frog: $frog")
}
} else -> {
// do nothing on changes
}
}
}
}
// fetch all objects of a type as a results collection, synchronously
val frogs: RealmResults<Frog> = realm.query<Frog>().find()
for(frog in frogs) {
Log.v("Frog: $frog")
}

You can query an embedded object directly or through the parent object. You can also use the EmbeddedRealmObject.parent() method to access the parent of the embedded object.

// Query an embedded object directly
val queryAddress: EmbeddedAddress =
realm.query<EmbeddedAddress>("state == 'FL'").find().first()
// Get the parent of an embedded object
val getParent: Contact =
queryAddress.parent()
// Query through the parent object
val queryContactAddresses: RealmResults<Contact> =
realm.query<Contact>("address.state == 'NY'")
.sort("name")
.find()

You can iterate and check the values of a RealmDictionary as you would a Kotlin Map.

// Find frogs who have forests with favorite ponds
val frogs = realm.query<Frog>().find()
val frogsWithFavoritePonds = frogs.query("favoritePondsByForest.@count > $0", 1).find()
val thisFrog = frogsWithFavoritePonds.first()
Log.v("${thisFrog.name} has favorite ponds in these forests: ")
// You can iterate through keys or values
for (key in thisFrog.favoritePondsByForest.keys) Log.v(key)
// Check if a dictionary contains a key
if (thisFrog.favoritePondsByForest.containsKey("Hundred Acre Wood")) {
Log.v("${thisFrog.name}'s favorite pond in Hundred Acre Wood is ${thisFrog.favoritePondsByForest["Hundred Acre Wood"]}")
}
// Check if a dictionary contains a value
if (thisFrog.favoritePondsByForest.containsValue("Picnic Pond")) {
Log.v("${thisFrog.name}'s lists Picnic Pond as a favorite pond")
}

You can query a RealmSet property:

realm.write {
// Create a Frog object named 'Kermit'
// with a RealmSet of favorite snacks
val frog = copyToRealm(
Frog().apply {
name = "Kermit"
favoriteSnacks.add(Snack().apply { name = "Flies" })
favoriteSnacks.add(Snack().apply { name = "Crickets" })
favoriteSnacks.add(Snack().apply { name = "Worms" })
}
)
// Query for frogs that have worms as a favorite snack
val frogs = query<Frog>("favoriteSnacks.name == $0", "Worms").find().first()
// Query for specific snacks
val wormsSnack = frog.favoriteSnacks.first { it.name == "Worms" }
}

You can check if the RealmSet contains one or more elements:

  • To check if the set contains a particular item, pass the element to set.contains().

  • To check if the RealmSet contains multiple items, pass the elements to set.containsAll().

Either method returns true if the set contains the specified elements.

val frog = query<Frog>("name == $0", "Kermit").find().first()
val snackSet = findLatest(frog)?.favoriteSnacks
// Check if the set contains a particular value
val wormSnack = snackSet?.first { it.name == "Worms" }
Log.v("Does Kermit eat worms?: ${snackSet?.contains(wormSnack)}") // true
// Check if the set contains multiple values
val containsAllSnacks = snackSet?.containsAll(snackSet)
Log.v("Does Kermit eat flies, crickets, and worms?: $containsAllSnacks") // true

Filter results to retrieve a specific segment of objects with realm.query(). In the argument of realm.query(), use Realm Query Language to perform filtering. Realm Query Language is a string-based query language that you can use to retrieve objects from a realm. Specify the object type as a type parameter passed to query().

For more information on constructing queries, refer to the Realm Query Language reference documentation.

// Find frogs where name is 'Michigan J. Frog'
val michiganFrogs: RealmResults<Frog> =
realm.query<Frog>("name = $0", "Michigan J. Frog").find()
// Find frogs where age > 3 AND species is 'Green'
val oldGreenFrogs: RealmResults<Frog> =
realm.query<Frog>("age > $0 AND species = $1", 3, "green" ).find()

You can use Realm Query Language (RQL) to query on properties that have Full-Text Search Indexes (FTS) on them. FTS supports Boolean matches and not relevance-based matches. To query these properties, use the TEXT predicate.

Words in the query are converted to tokens by a tokenizer using the following rules:

  • Tokens can only consist of characters from ASCII and the Latin-1 supplement (western languages). All other characters are considered whitespace.

  • Words split by a hyphen (-), for example full-text, are split into two tokens.

  • Tokens are diacritics- and case-insensitive.

You can search for an entire word or phrase or limit your results with the following characters:

  • Exclude results for a word by placing the - character in front of the word. For example, fiction -science would include all search results for fiction and exclude those that include the word science.

  • In Kotlin SDK version 1.11.0 and later, you can specify prefixes by placing the * character at the end of a word. For example, fict* would include all search results for fiction and fictitious. (The Kotlin SDK does not currently support suffix searches.)

In the following example, we query the Book.genre field:

// Find all books with "science fiction" as the genre
val scienceFiction =
realm.query<Book>("genre TEXT $0", "science fiction").find()
// Find all books with "fiction" but not "science" in the genre
val fictionNotScience =
realm.query<Book>("genre TEXT $0", "fiction -science").find()
// Find all books with "sci-" and "fi-" prefixes in the genre
val sciFi =
realm.query<Book>("genre TEXT $0", "sci* fi*").find()

To sort results, specify a sort in the query passed to realm.query() with the SORT keyword. Similarly, use DISTINCT to constrain results to unique values of a field, and LIMIT to cap the number of results. The SDK provides convenience methods on RealmQuery so you don't have to manually write the keywords:

When used on the same query in both RQL and method form, SORT, DISTINCT, and LIMIT execute in the order they're added to the query. This can impact the results returned from your query.

// sort in descending order, frogs with distinct owners, only the first 5, with convenience methods
val convenientlyOrganizedFrogs: Flow<ResultsChange<Frog>> =
realm.query<Frog>("name = $0", "George Washington")
.sort("age", Sort.DESCENDING).distinct("owner").limit(5).asFlow()
val asyncCallConvenience: Deferred<Unit> = async {
convenientlyOrganizedFrogs.collect { results ->
when (results) {
// print out initial results
is InitialResults<Frog> -> {
for (frog in results.list) {
Log.v("Frog: $frog")
}
} else -> {
// do nothing on changes
}
}
}
}
// sort in descending order, frogs with distinct owners, only the first 5, using RQL
val somewhatLessConvenientlyOrganizedFrogs: Flow<ResultsChange<Frog>> =
realm.query<Frog>("name = $0 SORT(age DESC) DISTINCT(owner) LIMIT(5)", "George Washington").asFlow()
val asyncCallLessConvenient: Deferred<Unit> = async {
somewhatLessConvenientlyOrganizedFrogs.collect { results ->
when (results) {
// print out initial results
is InitialResults<Frog> -> {
for (frog in results.list) {
Log.v("Frog: $frog")
}
} else -> {
// do nothing on changes
}
}
}
}

You can iterate through results using Flows.

Tip

See also:

To learn more about Kotlin Flows, check out the kotlinx.coroutines documentation on Flows.

To convert your results into a Flow, call realmQuery.asFlow(). Then iterate through the results with flow.collect():

// fetch frogs from the realm as Flowables
val frogsFlow: Flow<ResultsChange<Frog>> = realm.query<Frog>().asFlow()
// iterate through the flow with collect, printing each item
val frogsObserver: Deferred<Unit> = async {
frogsFlow.collect { results ->
when (results) {
// print out initial results
is InitialResults<Frog> -> {
for (frog in results.list) {
Log.v("Frog: $frog")
}
}
else -> {
// do nothing on changes
}
}
}
}
// ... some time later, cancel the flow so you can safely close the realm
frogsObserver.cancel()
realm.close()
←  Create Realm Objects - Kotlin SDKUpdate Realm Objects - Kotlin SDK →
Share Feedback
© 2023 MongoDB, Inc.

About

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