Supported Types - Kotlin SDK
On this page
This page describes the supported data types that you can use to define properties in your object model. For more information on how to define your object model, refer to Define an Object Model.
To learn how specific data types are mapped to BSON types in an App Services Schema, refer to Data Model Mapping in the Atlas App Services documentation.
Supported Data Types List
The Kotlin SDK supports the following Kotlin types, BSON types, and Realm-specific types, which you can use for unique identifiers, timestamps, counters, and collections.
The Kotlin SDK does not natively support:
user-defined enumeration properties. Refer to the Enums section for more information on how to use enums in your Realm objects.
Kotlin's built-in
Date
orInstant
. Refer to the RealmInstant section for more information on how to use timestamps in your Realm objects.
Realm object properties must be mutable and initialized when declared.
The Kotlin SDK does not currently support abstract properties. You
can declare properties optional (nullable) using the built-in
?
Kotlin operator, or you can assign a default value to a property
when you declare it.
Note
Realm stores all non-decimal numeric types as Long
values and all decimal numeric types as Double
values.
Kotlin Data Types
The following table lists the supported Kotlin data types and examples of how to declare them as required or optional properties in your object model.
Kotlin Data Type | Required | Optional | ||
---|---|---|---|---|
String |
|
| ||
Byte |
|
| ||
Short |
|
| ||
Int |
|
| ||
Long |
|
| ||
Float |
|
| ||
Double |
|
| ||
Boolean |
|
| ||
Char |
|
|
MongoDB BSON Types
The following table lists the supported MongoDB BSON data types and examples of how to declare them as required or optional properties in your object model. To use these types, you must import them from the org.mongodb.kbson package.
MongoDB BSON Type | Required | Optional | ||
---|---|---|---|---|
|
| |||
Decimal128 |
|
|
Realm-Specific Types
The following table lists the supported Realm-specific data types and examples of how to declare them as required or optional properties in your object model.
Realm-Specific Type | Required | Optional | ||
---|---|---|---|---|
|
| |||
|
| |||
N/A |
| |||
|
| |||
| N/A | |||
| N/A | |||
| N/A | |||
N/A |
| |||
N/A |
|
Unique Identifiers
The Kotlin SDK supports UUID
and ObjectId
as unique identifiers for Realm objects.
Note
Using UUID Instead of ObjectId
In general, you can use UUID
for any fields that function as a unique
identifier. Using UUID
might be particularly useful if you are migrating
data not stored in MongoDB since it is likely that your object's unique
identifiers are already of a UUID
type. Alternatively, using ObjectId
might be useful for a collection of data that already exists in MongoDB.
ObjectId
ObjectId
is a MongoDB-specific BSON type. It is a
12-byte, globally unique value that you can use as an identifier for objects.
It is nullable, indexable, and can
be used as a primary key.
You can initialize an ObjectId
using ObjectId()
.
Important
io.realm.kotlin.types.ObjectId Deprecated in v1.5.0
In Realm Kotlin SDK version 1.5.0 and newer,
io.realm.kotlin.types.ObjectId
is deprecated. You must import ObjectId
from
org.mongodb.kbson.ObjectId instead.
RealmUUID
UUID
(Universal Unique Identifier) is a 16-byte unique value
that you can use as an identifier for objects. It is nullable,
indexable, and can be used as a primary key.
Realm creates UUIDs with the RealmUUID type that conform to RFC 4122 version 4 and are created with random bytes.
You can generate a random RealmUUID
using RealmUUID.random()
or pass a UUID-formatted string to RealmUUID.from():
val uuid1 = RealmUUID.from("46423f1b-ce3e-4a7e-812f-004cf9c42d76") val uuid2 = RealmUUID.random()
MutableRealmInt (Counter)
The Kotlin SDK offers MutableRealmInt
as a special integer type that you can use as a logical counter to accurately
synchronize numeric changes across multiple distributed clients.
It behaves like a Long
but also supports increment
and decrement
methods that implement a
conflict-free replicated data type.
This ensures that numeric updates can be executed regardless of order to
converge to the same value.
A MutableRealmInt
property:
cannot be used as a primary key
cannot store null values, but it can be declared nullable (
MutableRealmInt?
)
Additionally, MutableRealmInt
fields:
are backed by Kotlin's numeric types, so no migration is required when changing a numeric field to
MutableRealmInt
.can use operators and infix functions similar to those provided by
Long
. However, note that any operations other thanset
,increment
, anddecrement
do not mutate the instance on which they are executed. Instead, they create a new, unmanagedMutableRealmInt
instance with the updated value.
Learn how to Create a MutableRealmInt (Counter) Property and Update a MutableRealmInt (Counter) Property.
RealmInstant (Timestamp)
You cannot store Kotlin's built-in Date
or Instant
types in Realm.
Instead, the Kotlin SDK uses the RealmInstant type to store time information as a Unix epoch timestamp.
If you need timestamp data in a form other than RealmInstant
, you
can add conversion code to your model class based on the following
example:
// model class that stores an Instant (kotlinx-datetime) field as a RealmInstant via a conversion class RealmInstantConversion : RealmObject { private var _timestamp: RealmInstant = RealmInstant.from(0, 0) public var timestamp: Instant get() { return _timestamp.toInstant() } set(value) { _timestamp = value.toRealmInstant() } } fun RealmInstant.toInstant(): Instant { val sec: Long = this.epochSeconds // The value always lies in the range `-999_999_999..999_999_999`. // minus for timestamps before epoch, positive for after val nano: Int = this.nanosecondsOfSecond return if (sec >= 0) { // For positive timestamps, conversion can happen directly Instant.fromEpochSeconds(sec, nano.toLong()) } else { // For negative timestamps, RealmInstant starts from the higher value with negative // nanoseconds, while Instant starts from the lower value with positive nanoseconds // TODO This probably breaks at edge cases like MIN/MAX Instant.fromEpochSeconds(sec - 1, 1_000_000 + nano.toLong()) } } fun Instant.toRealmInstant(): RealmInstant { val sec: Long = this.epochSeconds // The value is always positive and lies in the range `0..999_999_999`. val nano: Int = this.nanosecondsOfSecond return if (sec >= 0) { // For positive timestamps, conversion can happen directly RealmInstant.from(sec, nano) } else { // For negative timestamps, RealmInstant starts from the higher value with negative // nanoseconds, while Instant starts from the lower value with positive nanoseconds // TODO This probably breaks at edge cases like MIN/MAX RealmInstant.from(sec + 1, -1_000_000 + nano) } }
RealmAny (Mixed)
Changed in version 2.0.0: RealmAny
can hold lists and dictionaries of mixed data.
RealmAny
represents a non-nullable mixed data type. It behaves like the value type
that it contains. RealmAny
can hold:
supported Kotlin data types (note that
Byte
,Char
,Int
,Long
, andShort
values are converted internally toint64_t
values)RealmList
andRealmDictionary
collections of mixed datathe following Realm-specific types:
RealmInstant
RealmUUID
RealmObject (holds a reference to the object, not a copy of it)
RealmAny
cannot hold EmbeddedRealmObject
types, RealmSet
, or
another RealmAny
.
RealmAny
properties:
are indexable but cannot be used as a primary key
must be declared nullable (
RealmAny?
), but they cannot store null valuescan be aggregated with RealmQuery.max, RealmQuery.min, and RealmQuery.sum.
can be sorted. Sort order from highest to lowest:
Boolean
Byte
,Double
,Decimal128
,Int
,Float
,Long
,Short
byte[]
,String
Date
ObjectId
UUID
RealmObject
You can store multiple RealmAny
instances in RealmList
,
RealmDictionary
, or RealmSet
fields.
Tip
Handle Polymorphism with Conditional Expressions
Because you must know the stored type to extract its value, we
recommend using a when
expression to handle the
RealmAny
type and its possible inner value class.
Collections as Mixed
In version 2.0.0 and later, a RealmAny
data type can
hold collections (a list or dictionary, but not a set) of RealmAny
elements. You can use mixed collections to
model unstructured or variable data. For more information, refer to
Define Unstructured Data.
You can nest mixed collections up to 100 levels.
You can query mixed collection properties and register a listener for changes, as you would a normal collection.
You can find and update individual mixed collection elements
You cannot store sets or embedded objects in mixed collections.
To use mixed collections in your app, define the mixed type
property in your data model the same way you would any other RealmAny
type.
Then, create the list or dictionary collections using RealmAny.create()
.
Collection Types
The Kotlin SDK offers several collection types that you can use as properties in your data model. A collection is an object that contains zero or more instances of one supported data type. Realm collections are homogenous (all objects in a collection are of the same type) and are backed by their corresponding built-in Kotlin classes.
Collection types are non-null. When you define a collection property, you must initialize it. For more information, refer to Create a Collection.
RealmList
The RealmList type implements Kotlin's List interface. Unmanaged lists behave like Kotlin's MutableList.
A RealmList
represents a to-many relationship
containing:
any of the supported Kotlin data types
any of the supported BSON types
RealmList<E>
is a non-null type, where:
lists of
RealmObject
orEmbeddedRealmObject
elements cannot be nullablelists of any other supported elements can be nullable (
RealmList<E?>
)
RealmSet
The RealmSet type implements Kotlin's Set interface. Unmanaged sets behave like Kotlin's MutableSet.
A RealmSet
represents a to-many relationship
containing distinct values of:
any of the supported Kotlin data types
any of the supported BSON types
You cannot use EmbeddedRealmObject
elements in a RealmSet
.
RealmSet<E>
is a non-null type, where:
sets of
RealmObject
elements cannot be nullablesets of any other supported elements can be nullable (
RealmSet<E?>
)
RealmMap/RealmDictionary
The RealmMap
type implements Kotlin's Map
interface and is an associative array that contains key-value String
pairs
with unique keys.
RealmDictionary
is a specialized RealmMap
that accepts a String
key and non-string values.
Unmanaged dictionaries behave
like Kotlin's LinkedHashMap.
RealmDictionary
values can be:
any of the supported Kotlin data types
any of the supported BSON types
RealmDictionary<K, V>
is a non-null type, where:
keys must be strings
RealmObject
orEmbeddedRealmObject
values must be nullable (RealmDictionary<K, V?>
)any other supported element values can be nullable
RealmObjects as Properties
You can use RealmObject
and any subclasses, except
AsymmetricRealmObject
as properties in your object model.
Important
AsymmetricRealmObject
cannot be used as properties.
For more information, refer to Asymmetric Objects.
RealmObjects
A RealmObject type represents a custom object that you can use as a property.
RealmObject
properties:
must be declared nullable
can be used as elements in collections
can be held as a
RealmAny
valuecannot be used as a primary key
You can also reference one or more Realm objects from another through to-one and to-many relationships. For more information, refer to the Relationships page.
Backlinks
A backlink represents an inverse, to-many relationship between a
RealmObject
and one or more RealmObject
or between a RealmObject
and an EmbeddedRealmObject
. Backlinks cannot be null.
Backlinks implement:
the BacklinksDelegate type for
RealmObject
backlinksthe EmbeddedBacklinksDelegate type for
EmbeddedRealmObject
backlinks
For more information, refer to Inverse Relationships.
EmbeddedRealmObject
An EmbeddedRealmObject
is a special type of RealmObject
.
EmbeddedRealmObject
properties:
must be nullable objects within the parent object
must be nullable values within a dictionary
cannot be nullable elements within a list
cannot be used as a primary key
can be properties within an asymmetric object
For more information, refer to Embedded Objects.
Geospatial Types
New in version 1.11.0.
The Kotlin SDK supports geospatial queries using the following data types:
Important
Cannot Persist Geospatial Data Types
Currently, geospatial data types cannot be persisted. For example, you can't
declare a property that is of type GeoBox
.
These types can only be used as arguments for geospatial queries.
For more information on querying with geospatial data, refer to Geospatial Data.
Enums
The Kotlin SDK does not natively support enumerations, or enums. To use enums in a Realm object class, define a field with a type matching the underlying data type of your enum.
Then, create getters and setters for the field that convert the field value between the underlying value and the enum type.
enum class EnumClass(var state: String) { NOT_STARTED("NOT_STARTED"), IN_PROGRESS("IN_PROGRESS"), COMPLETE("COMPLETE") } class EnumObject : RealmObject { var name: String? = null private var state: String = EnumClass.NOT_STARTED.state var stateEnum: EnumClass get() = EnumClass.valueOf(state) set(value) { state = value.state } }