Getting and writing data
Put, Delete, Get
Kodein-DB does not know the difference between Put and Update. If you put a document that already exists in the database, it will be overwritten (you can, however, manually check the existence and state of an overwritten model).
To put a document inside the database, simply use the put
method:
val key = db.put(user) (1)
1 | The put method returns the Key that refers to the model. |
You can as easily delete a document:
db.delete(key)
To get a model, simply use the get
method:
val user = db[key]
Handling Keys
Definition
A Key
is the unique identifier that identifies a document (and the associated model) inside the database.
It contains the following information:
-
The type of the document (which is also the type of the model, unless you’re using polymorphism).
-
The Id of the document.
You can think of Kodein-DB as a file cabinet:
|
A key is specific to a Kodein-DB instance: a key refers to a model relative to a specific Kodein-DB. Do not share a Key: the same model with the same ID may give 2 different keys on two different databases. |
Creating a Key
From a model
You can always ask Kodein-DB to provide you with the key of a specific model:
val key = db.newKey(user)
You can create a key from any model, whether it exists in database or not.
Using newKeyFrom does not ensure you that the model exists in database, nor does it put it.
|
From ID values
You can easily create a key from its ID value(s):
val key = db.newKey<User>("01234567-89ab-cdef-0123-456789abcdef")
If you are using composite IDs, you need to provide all values of the ID. Creating a key with a composite ID
|
From a Base64 representation
Once you have a Key
(either from put
or newKey
), you can serialize it to Base64:
val b64 = key.toBase64()
Then, you can re-create a key from a Base64 string:
val key = db.newKeyFromB64(b64)
Even when serialized in Base64, a Key is only valid on the Kodein-DB that created it. |
Iteration
Getting a cursor
To iterate over a collection or a subset of a collection, you need to create cursor.
Cursors are Closeable ! You need to either close them after use, or to call use on them.
|
You can iterate:
-
Over all models of a collection, ordered by ID:
val cursor = db.find<User>().all()
-
Over all models of a collection whose composite ID begins with a specific value, ordered by id:
val cursor = db.find<User>().byId("Doe")
-
Over all models of a collection, ordered by an index:
val cursor = db.find<User>().byIndex("lastName")
-
Over all models of a collection with the specific index (composite or not) value, ordered by that index:
val cursor = db.find<User>().byIndex("lastName", "Doe")
-
Over all models of the database:
val cursor = db.findAll()
When using findAll()
on multiplatform projects, you must define a type table that defines all model classes!
Cursors are working on a snapshot of the database. This means that once an iterator is created, subsequent writes to the database won’t be reflected in the result of the iteration. |
Using a cursor
As is
By default, a cursor points to the first value of the matching query.
-
You can get the key and model with
key()
andmodel()
. -
You can move the cursor one item with
next()
andprevious()
, or directly to the start or end of the matching items withseekToFirst
orseekToLast
. -
Each time the cursor moves, you need to check whether it is still valid with
isValid()
.
db.find<User>().byIndex("lastName", "Doe").use { cursor -> (1)
while (cursor.isValid()) {
val model = cursor.model()
println(model)
cursor.next()
}
}
1 | use ensures to close the cursor when iteration ends. |
As a sequence
You can easily transform a Cursor
to a Sequence
.
Note that when you do, the cursor will be automatically closed when the sequence ends.
You can use either models()
that creates a squence of models, or entries
, that create a sequence of model and key pairs.
db.find<User>().byIndex("lastName", "Doe").models().forEach {
println(it)
}
The sequence will only close when the last item has been collected! The following code will not close the associated cursor and create a resource leak! Creating a cursor leak
The correct way to do this is as such: Getting the first 3 items without resource leak:
|