Docs

Kotlin: Firestore-compatible API

Firebase-style collection, document and query references on top of Sovaria documents, for moving a Firebase app over with the Kotlin SDK.

Updated Oct 24, 2026

Firebase-style collection, document and query references on top of Sovaria documents, for moving a Firebase app over. Every call runs as the client's signed-in user, so your project's policies and row-level security apply. Types and members are listed in source order; each one links to its HTTP endpoint where it maps to one.

#Types and members

FirebaseFirestore

The Firebase Android SDK's Firestore API on Sovaria documents: move an app by changing imports (com.google.firebase.firestore.* → in.sovaria.firestore.*) and how db is made. Names, arguments and shapes follow Firebase (data, exists(), documentChanges, ListenerRegistration, SetOptions.merge(), snapshots() flows as in the KTX library). Operations are suspend functions instead of Tasks. Underneath it is the Sovaria collection API, so collection rules and row policies decide every read and write. Timestamps are stored as ISO-8601 strings (Timestamp and Date values you write are converted; Timestamp.parse reads one back), and there is no offline document cache.

class FirebaseFirestore private constructor(val sovaria: Sovaria)

FirebaseFirestore.getInstance

The Firestore handle for a Sovaria client (one per client).

fun getInstance(sovaria: Sovaria): FirebaseFirestore

FirebaseFirestore.collection

collection("users") or collection("users/$uid/posts").

fun collection(collectionPath: String): CollectionReference

FirebaseFirestore.document

document("users/$uid").

fun document(documentPath: String): DocumentReference

FirebaseFirestore.collectionGroup

Every collection with this id at any depth (comments, posts/p1/comments, …).

fun collectionGroup(collectionId: String): Query

FirebaseFirestore.batch

fun batch(): WriteBatch

FirebaseFirestore.runTransaction

Run function and commit its writes atomically; retried (up to maxAttempts) when a document it read changed meanwhile.

suspend fun <T> runTransaction(maxAttempts: Int = 5, function: suspend (Transaction) -> T): T

Unlike Firebase's Transaction.Function, it is a suspend lambda (reads go to the server).

Timestamp

A point in time. Stored as an ISO-8601 string in Sovaria.

data class Timestamp(val seconds: Long, val nanoseconds: Int) : Comparable<Timestamp>

Timestamp.Timestamp.init

Create an instance.

constructor(date: Date) : this(Math.floorDiv(date.time, 1000L), (Math.floorMod(date.time, 1000L) * 1_000_000).toInt())

Timestamp.toDate

fun toDate(): Date

Timestamp.toInstant

fun toInstant(): Instant

Timestamp.toIso

2026-01-02T03:04:05.000Z (milliseconds, UTC).

fun toIso(): String

Timestamp.compareTo

override fun compareTo(other: Timestamp)

Timestamp.now

fun now(): Timestamp

Timestamp.parse

Read back a stored timestamp (an ISO string).

fun parse(iso: String): Timestamp

VectorValue

A vector value (FieldValue.vector(...)); stored as an array of numbers.

data class VectorValue(val values: DoubleArray)

VectorValue.toArray

fun toArray(): DoubleArray

VectorValue.equals

override fun equals(other: Any?)

VectorValue.hashCode

override fun hashCode()

FieldPath

A field path: FieldPath.of("address", "city"), or FieldPath.documentId() to filter or order by the id.

class FieldPath private constructor(val segments: List<String>)

FieldPath.of

fun of(vararg fieldNames: String)

FieldPath.documentId

fun documentId()

FieldPath.equals

override fun equals(other: Any?)

FieldPath.hashCode

override fun hashCode()

FieldPath.toString

override fun toString()

FieldValue

Atomic field updates, applied by the server inside the commit.

class FieldValue private constructor(internal val op: String, internal val value: Any? = null)

FieldValue.delete

fun delete()

FieldValue.serverTimestamp

fun serverTimestamp()

FieldValue.arrayUnion

fun arrayUnion(vararg elements: Any?)

FieldValue.arrayRemove

fun arrayRemove(vararg elements: Any?)

FieldValue.increment

fun increment(l: Long)

FieldValue.increment

fun increment(d: Double)

FieldValue.increment

fun increment(i: Int)

FieldValue.vector

fun vector(values: DoubleArray)

SetOptions

SetOptions.merge() or SetOptions.mergeFields("a", "b.c").

class SetOptions private constructor(internal val merge: Boolean, internal val fields: List<String>?)

SetOptions.merge

fun merge()

SetOptions.mergeFields

fun mergeFields(vararg fields: String)

SetOptions.mergeFieldPaths

fun mergeFieldPaths(fields: List<FieldPath>)

DocumentReference

class DocumentReference internal constructor(val firestore: FirebaseFirestore, val path: String)

DocumentReference.id

A property.

val id: String get()

DocumentReference.parent

A property.

val parent: CollectionReference get()

DocumentReference.collection

fun collection(collectionPath: String)

DocumentReference.get

suspend fun get(): DocumentSnapshot

DocumentReference.set

Replace the document, or merge into it with SetOptions.merge().

suspend fun set(data: Map<String, Any?>, options: SetOptions? = null)

DocumentReference.update

Change fields ("a.b" dotted paths and FieldPath keys allowed); fails with 404 when it doesn't exist.

suspend fun update(data: Map<String, Any?>)

DocumentReference.update

suspend fun update(field: String, value: Any?, vararg moreFieldsAndValues: Any?)

DocumentReference.update

suspend fun update(field: FieldPath, value: Any?, vararg moreFieldsAndValues: Any?)

DocumentReference.delete

suspend fun delete()

DocumentReference.addSnapshotListener

The document now and after every change.

fun addSnapshotListener(listener: EventListener<DocumentSnapshot>): ListenerRegistration

remove() stops it.

DocumentReference.addSnapshotListener

fun addSnapshotListener(executor: Executor?, listener: EventListener<DocumentSnapshot>): ListenerRegistration

DocumentReference.snapshots

KTX: the document as a Flow.

fun snapshots(): Flow<DocumentSnapshot>

DocumentReference.equals

override fun equals(other: Any?)

DocumentReference.hashCode

override fun hashCode()

DocumentReference.toString

override fun toString()

Filter

One filter or an or / and group: where(Filter.or(Filter.equalTo("a", 1), Filter.lessThan("b", 2))).

class Filter private constructor(internal val wire: Any)

Filter.equalTo

fun equalTo(field: Any, value: Any?)

Filter.notEqualTo

fun notEqualTo(field: Any, value: Any?)

Filter.lessThan

fun lessThan(field: Any, value: Any)

Filter.lessThanOrEqualTo

fun lessThanOrEqualTo(field: Any, value: Any)

Filter.greaterThan

fun greaterThan(field: Any, value: Any)

Filter.greaterThanOrEqualTo

fun greaterThanOrEqualTo(field: Any, value: Any)

Filter.arrayContains

fun arrayContains(field: Any, value: Any)

Filter.arrayContainsAny

fun arrayContainsAny(field: Any, values: List<Any?>)

Filter.inArray

fun inArray(field: Any, values: List<Any?>)

Filter.notInArray

fun notInArray(field: Any, values: List<Any?>)

Filter.or

Documents matching any of the filters (at most 30 OR terms after expansion).

fun or(vararg filters: Filter)

Filter.and

Documents matching all of the filters, for nesting inside or.

fun and(vararg filters: Filter)

Query

open class Query internal constructor(
    val firestore: FirebaseFirestore,
    /** The collection path (a collection id for a collection group). */
    val path: String,
    internal val body: Map<String, Any?>,
    internal val isGroup: Boolean = false,
)

Query.parameters

The request body (for tests and debugging).

val parameters: Map<String, Any?> get()

Query.where

fun where(filter: Filter): Query

Query.whereEqualTo

fun whereEqualTo(field: String, value: Any?)

Query.whereEqualTo

fun whereEqualTo(field: FieldPath, value: Any?)

Query.whereNotEqualTo

fun whereNotEqualTo(field: String, value: Any?)

Query.whereNotEqualTo

fun whereNotEqualTo(field: FieldPath, value: Any?)

Query.whereLessThan

fun whereLessThan(field: String, value: Any)

Query.whereLessThan

fun whereLessThan(field: FieldPath, value: Any)

Query.whereLessThanOrEqualTo

fun whereLessThanOrEqualTo(field: String, value: Any)

Query.whereLessThanOrEqualTo

fun whereLessThanOrEqualTo(field: FieldPath, value: Any)

Query.whereGreaterThan

fun whereGreaterThan(field: String, value: Any)

Query.whereGreaterThan

fun whereGreaterThan(field: FieldPath, value: Any)

Query.whereGreaterThanOrEqualTo

fun whereGreaterThanOrEqualTo(field: String, value: Any)

Query.whereGreaterThanOrEqualTo

fun whereGreaterThanOrEqualTo(field: FieldPath, value: Any)

Query.whereArrayContains

fun whereArrayContains(field: String, value: Any)

Query.whereArrayContains

fun whereArrayContains(field: FieldPath, value: Any)

Query.whereArrayContainsAny

fun whereArrayContainsAny(field: String, values: List<Any?>)

Query.whereArrayContainsAny

fun whereArrayContainsAny(field: FieldPath, values: List<Any?>)

Query.whereIn

fun whereIn(field: String, values: List<Any?>)

Query.whereIn

fun whereIn(field: FieldPath, values: List<Any?>)

Query.whereNotIn

fun whereNotIn(field: String, values: List<Any?>)

Query.whereNotIn

fun whereNotIn(field: FieldPath, values: List<Any?>)

Query.orderBy

fun orderBy(field: String, direction: Direction = Direction.ASCENDING)

Query.orderBy

fun orderBy(field: FieldPath, direction: Direction = Direction.ASCENDING)

Query.limit

fun limit(limit: Long)

Query.limitToLast

fun limitToLast(limit: Long)

Query.startAt

fun startAt(vararg fieldValues: Any?)

Query.startAfter

fun startAfter(vararg fieldValues: Any?)

Query.endAt

fun endAt(vararg fieldValues: Any?)

Query.endBefore

fun endBefore(vararg fieldValues: Any?)

Query.startAt

fun startAt(snapshot: DocumentSnapshot)

Query.startAfter

fun startAfter(snapshot: DocumentSnapshot)

Query.endAt

fun endAt(snapshot: DocumentSnapshot)

Query.endBefore

fun endBefore(snapshot: DocumentSnapshot)

Query.get

suspend fun get(): QuerySnapshot

Query.addSnapshotListener

Live results: the listener runs with the first snapshot and after every change.

fun addSnapshotListener(listener: EventListener<QuerySnapshot>): ListenerRegistration

remove() stops it.

Query.addSnapshotListener

As above, calling listener on executor (e.g.

fun addSnapshotListener(executor: Executor?, listener: EventListener<QuerySnapshot>): ListenerRegistration

ContextCompat.getMainExecutor(context)).

Query.snapshots

KTX: the live results as a Flow.

fun snapshots(): Flow<QuerySnapshot>

Query.count

count().get(AggregateSource.SERVER).count.

fun count()

Query.aggregate

aggregate(AggregateField.count(), AggregateField.sum("price")).get(AggregateSource.SERVER).

fun aggregate(field: AggregateField, vararg fields: AggregateField)

Query.findNearest

Vector search: this query's filters first, then the limit documents whose vectorField is closest.

fun findNearest(
    vectorField: Any,
    queryVector: VectorValue,
    limit: Int,
    distanceMeasure: DistanceMeasure,
    distanceResultField: String? = null,
    distanceThreshold: Double? = null,
): VectorQuery

Direction

enum class Direction

CollectionReference

class CollectionReference internal constructor(firestore: FirebaseFirestore, path: String) : Query(firestore, path, emptyMap())

CollectionReference.id

A property.

val id: String get()

CollectionReference.parent

The document this subcollection belongs to, or null for a top-level collection.

val parent: DocumentReference? get()

CollectionReference.document

A new document with a random id.

fun document(): DocumentReference

CollectionReference.document

fun document(documentPath: String): DocumentReference

CollectionReference.add

Create a document with a new id.

suspend fun add(data: Map<String, Any?>): DocumentReference

DistanceMeasure

enum class DistanceMeasure(internal val wire: String)

VectorQuery

class VectorQuery internal constructor(private val query: Query, private val body: Map<String, Any?>)

VectorQuery.get

suspend fun get(): QuerySnapshot

AggregateField

class AggregateField private constructor(internal val op: String, internal val fieldName: String?)

AggregateField.equals

override fun equals(other: Any?)

AggregateField.hashCode

override fun hashCode()

AggregateField.count

fun count()

AggregateField.sum

fun sum(field: String)

AggregateField.sum

fun sum(field: FieldPath)

AggregateField.average

fun average(field: String)

AggregateField.average

fun average(field: FieldPath)

AggregateSource

enum class AggregateSource

AggregateQuery

class AggregateQuery internal constructor(val query: Query, private val fields: List<AggregateField>)

AggregateQuery.get

suspend fun get(source: AggregateSource = AggregateSource.SERVER): AggregateQuerySnapshot

AggregateQuerySnapshot

class AggregateQuerySnapshot internal constructor(private val values: Map<String, Any?>)

AggregateQuerySnapshot.count

A property.

val count: Long get()

AggregateQuerySnapshot.get

The value for field (a Number, or null when there was nothing to average).

fun get(field: AggregateField): Number?

AggregateQuerySnapshot.getDouble

fun getDouble(field: AggregateField): Double?

AggregateQuerySnapshot.getLong

fun getLong(field: AggregateField): Long?

SnapshotMetadata

data class SnapshotMetadata(private val pendingWrites: Boolean, val isFromCache: Boolean)

SnapshotMetadata.hasPendingWrites

fun hasPendingWrites()

DocumentSnapshot

open class DocumentSnapshot internal constructor(val reference: DocumentReference, internal val raw: RawDoc)

DocumentSnapshot.id

A property.

val id: String get()

DocumentSnapshot.exists

fun exists(): Boolean

DocumentSnapshot.metadata

A property.

val metadata: SnapshotMetadata get()

DocumentSnapshot.data

The data, or null when the document doesn't exist.

open val data: Map<String, Any?>? get()

DocumentSnapshot.get

A field by dotted path (get("address.city")) or FieldPath; null when missing.

fun get(field: String): Any?

DocumentSnapshot.get

fun get(field: FieldPath): Any?

DocumentSnapshot.contains

Whether the field exists (it may hold null).

fun contains(field: String): Boolean

DocumentSnapshot.getString

fun getString(field: String)

DocumentSnapshot.getLong

fun getLong(field: String)

DocumentSnapshot.getDouble

fun getDouble(field: String)

DocumentSnapshot.getBoolean

fun getBoolean(field: String)

DocumentSnapshot.getTimestamp

A stored ISO-8601 timestamp as a Timestamp.

fun getTimestamp(field: String)

DocumentSnapshot.getDate

fun getDate(field: String)

QueryDocumentSnapshot

class QueryDocumentSnapshot internal constructor(reference: DocumentReference, raw: RawDoc) : DocumentSnapshot(reference, raw)

QueryDocumentSnapshot.data

A property.

override val data: Map<String, Any?> get()

DocumentChange

class DocumentChange internal constructor(val type: Type, val document: QueryDocumentSnapshot, val oldIndex: Int, val newIndex: Int)

Type

enum class Type

QuerySnapshot

class QuerySnapshot internal constructor(val query: Query, docs: List<RawDoc>, changes: List<Change>) : Iterable<QueryDocumentSnapshot>

QuerySnapshot.documents

A property.

val documents: List<QueryDocumentSnapshot>

QuerySnapshot.documentChanges

A property.

val documentChanges: List<DocumentChange>

QuerySnapshot.size

fun size()

QuerySnapshot.isEmpty

A property.

val isEmpty: Boolean get()

QuerySnapshot.metadata

A property.

val metadata: SnapshotMetadata

QuerySnapshot.iterator

override fun iterator()

WriteBatch

Writes committed together: every one or none.

class WriteBatch internal constructor(private val firestore: FirebaseFirestore)

WriteBatch.set

fun set(documentRef: DocumentReference, data: Map<String, Any?>, options: SetOptions? = null)

WriteBatch.update

fun update(documentRef: DocumentReference, data: Map<String, Any?>)

WriteBatch.update

fun update(documentRef: DocumentReference, field: String, value: Any?, vararg moreFieldsAndValues: Any?)

WriteBatch.delete

fun delete(documentRef: DocumentReference)

WriteBatch.commit

suspend fun commit()

Transaction

Read every document first, then write; the commit fails (and is retried) if a read document changed.

class Transaction internal constructor(private val firestore: FirebaseFirestore)

Transaction.get

suspend fun get(documentRef: DocumentReference): DocumentSnapshot

Transaction.set

fun set(documentRef: DocumentReference, data: Map<String, Any?>, options: SetOptions? = null)

Transaction.update

fun update(documentRef: DocumentReference, data: Map<String, Any?>)

Transaction.update

fun update(documentRef: DocumentReference, field: String, value: Any?, vararg moreFieldsAndValues: Any?)

Transaction.delete

fun delete(documentRef: DocumentReference)

interface

fun interface EventListener<T>

missing

fun missing(path: String)

interface

fun interface ListenerRegistration

groupPollMs

A server without collection-group listeners (older): the group query is re-run this often.

@Volatile var groupPollMs