Dynamic API
Dependencies
Add repository URL https://s01.oss.sonatype.org/content/repositories/snapshots/ for SNAPSHOT versions.
plugins {
kotlin("plugin.serialization")
}
dependencies {
implementation("io.firestore4k:dynamic-api:$latestVersion")
}
Model
Example
In the sample code below, we will define model for:
/users/{useri-d}/messages/{message-id}
So, we have 2 collections - users
and messages
, each of the collection have documents under them.
users
will be a root collection
.
messages
will be a sub collection
under users
.
Entity classes
Define Kotlin data class
s for the firestore document
s.
Important
Annotate them with @kotlinx.serialization.Serializable
@kotlinx.serialization.Serializable
data class User(
val name: String,
val email: String,
)
@kotlinx.serialization.Serializable
data class Message(
val from: String,
val to: String,
val subject: String,
val body: String,
)
Collections
Define collections - users
and messages
.
val users = collection("users")
val messages = collection("messages")
Warning
Unlike typed collections, we cannot define hierarchy of collections in dynamic-api
.
So an incorrect collection hierarchy will NOT be detected at compile-time.
messages / "message1" / users / "user1"
firestore path expression
DSL to express Firestore collection & document path.
val users = collection("users")
val messages = collection("messages")
// /users
users
// /users/user1
users / "user1"
// /users/user1/message
users / "user1" / messages
// /users/user1/message/message1
users / "user1" / messages / "message1"
Info
dynamic-api
only enforces path to be collection / id / collection / id / ...
.
There are no checks for collection hierarchy.
Warning
Unlike typed Identity value classes (optional), document IDs are String
in dynamic-api
.
So these incorrect IDs will NOT be detected at compile-time.
users / "message1" / messages / "user1"
CRUD operations
Use collection & document path for operations.
add
// add (ID auto generated by Firestore)
// add(<collection path>, <document object>): <String Id>
val userId: String = add(users, User())
put
// put (create or update)
// put(<document path>, <document object>)
put(users / "user1", User())
get
// get
// get(<document path>): <document object>
val user = get<User>(users / "user1")
Warning
dynamic-api
does not check if correct data class
is used in generics.
So an incorrect class in generics will NOT be detected at compile-time.
val user = get<Message>(users / "user1")
get all
// get all
// getAll(<collection path>): Collection<document object>
val messages = getAll<Message>(users / "user1" / messages)
Warning
dynamic-api
does not check if correct data class
is used in generics.
So an incorrect class in generics will NOT be detected at compile-time.
val messages = getAll<User>(users / "user1" / messages)
delete document
// delete document and its child entities
// This can be a document under root collection or sub-collection.
// deleteDocument(<document path>)
deleteDocument(users / "user1")
delete collection
// delete collection and its child entities.
// This can be root collection or sub-collection.
// deleteCollection(<collection path>)
deleteCollection(users)