Basics

The purpose of this tutorial is to get you started with the most common kantan.mongodb use cases. Further tutorials will tackle more advanced use cases, or take specific bits of this one and go into more details.

Example type

Type declaration

In this tutorial, we’ll be reading and writing values of the following type:

import java.util.UUID

case class User(id: java.util.UUID, name: String, age: Int)

Not exactly the most exciting type in the world, but enough for us to go through some simple mongo operations.

MongoDB integration

In order to be able to use our User type with kantan.mongodb, we need to provide implicit instances of BsonDocumentDecoder (to be able to read values from mongo) and BsonDocumentEncoder (to be able to write values to mongo).

This is more conveniently achieved through a BsonDocumentCodec, which wraps both:

import kantan.mongodb._

implicit val userCodec: BsonDocumentCodec[User] =
  BsonDocumentCodec.caseCodec("_id", "name", "age")(User.apply _)(User.unapply _)

Let’s not worry too much about the details of this yet, we’ll study encoders and decoders in more depths later.

Accessing a collection

In order to start working with mongo, the first thing to do is to create a client:

val client = MongoClient.local()
// client: kantan.mongodb.MongoClient = MongoClient(127.0.0.1:27017)

This connects to the local mongo instance, MongoClient has more options if you need them.

Once you have a client, you can get an instance of MongoDatabase through the database method, then an instance of MongoCollection through the collection method:

val col: MongoCollection[User] = client.database("kantan_mongodb").collection("users")
// col: kantan.mongodb.MongoCollection[User] = MongoCollection(kantan_mongodb.users)

Note how our MongoCollection has a type parameter, User, which represents the kind of values it’ll know to work with.

Let’s make sure it’s clear before we start inserting documents:

col.deleteAll()
// res2: kantan.mongodb.MongoResult[kantan.mongodb.DeleteResult] = Success(Acknowledged(2))

Working with documents

Document insertion

Now that we have an empty collection, let’s create a few documents. We can simply call one of the various insert methods, such as insertMany, with parameters of type User:

col.insertMany(
  User(UUID.randomUUID(), "Peter", 15),
  User(UUID.randomUUID(), "Bruce", 25),
  User(UUID.randomUUID(), "Tony", 21)
)
// res3: kantan.mongodb.MongoResult[Unit] = Success(())

Document lookup

Now that our collection contains data, we can try and locate documents. kantan.mongodb provides convenient helpers for collection querying in kantan.mongodb.query:

import kantan.mongodb.query._

This defines various query operators, such as $eq:

col.find($eq("name", "Peter")).foreach(println _)
// Success(User(aac8d80f-9b0e-4d9f-9fa9-d4a1670ad6e8,Peter,15))

Document update

We can also easily update documents through one of the various update methods. For example, updateOne:

col.updateOne($eq("name", "Tony"), $set("name", "Riri") && $set("age", 15))
// res5: kantan.mongodb.MongoResult[kantan.mongodb.UpdateResult] = Success(Update(1,Some(1)))

col.find().foreach(println _)
// Success(User(aac8d80f-9b0e-4d9f-9fa9-d4a1670ad6e8,Peter,15))
// Success(User(6b59edf4-e0bd-4a1a-b956-a214fcbf50bb,Bruce,25))
// Success(User(58d9ed73-953c-4300-ab86-6faa1568e431,Riri,15))

Document deletion

Finally, deletion is done through one of the various delete methods. For example, deleteOne:

col.deleteOne($eq("name", "Riri"))
// res7: kantan.mongodb.MongoResult[kantan.mongodb.DeleteResult] = Success(Acknowledged(1))

And we can verify that Riri is not in our collection anymore:

col.find().foreach(println _)
// Success(User(aac8d80f-9b0e-4d9f-9fa9-d4a1670ad6e8,Peter,15))
// Success(User(6b59edf4-e0bd-4a1a-b956-a214fcbf50bb,Bruce,25))

Cleanup

When done with an instance of MongoClient, it’s import to close it in order to free resources:

client.close()

Other tutorials: