Matthias Braun Matthias Braun - 21 days ago 6
Scala Question

How to update document in CouchDB with Scala

I'd like to change a document in my CouchDB database using the great Scala client CouchDB-Scala.

I know the ID of the document and I got the new data ready. As an example, let's say my data is this case class:

case class Person (name: String, age: Int)


I'd like to do something along the lines of

val newData = Person("new name", 56)
val docId = "4e5720837e3c057facbaa4e68b01a787"
update(newData, docId)

Answer

This works for me:

import com.ibm.couchdb._
import scala.concurrent.duration._

def update(newData: Person, docId: String) = {

  val docs = dbApi.docs

  val updateActions = for {
    oldDoc <- docs.get[Person](docId)
    newDoc = oldDoc.copy(doc = newData)
    updateResult <- docs.update(newDoc)

  } yield updateResult

  val timeoutLength = Duration.create(15, SECONDS) 
  updateActions.unsafePerformSyncAttemptFor(timeoutLength)
}

And here is dbApi that also performs database setup:

import scalaz.concurrent.Task
import scalaz.{-\/, \/, \/-}

val dbApi = {
  val couchDbHostName = "couchDbForMyApp"
  val couch = CouchDb(couchDbHostName, 5984)
  // Define a type mapping used to transform class names into the doc kind
  val typeMapping = TypeMapping(classOf[Person] -> "Person")
  val dbName = "myApp-database"

  // Trying to create a database with the same name as an existing one results in an error
  createDatabaseIfItDoesntExistSync(dbName, couch)

  // Return an instance of the DB API by name and type mapping
  couch.db(dbName, typeMapping)
}

def await[T](future: Task[T]): Throwable \/ T = future.unsafePerformSyncAttempt

def createDatabaseIfItDoesntExistSync(dbName: String, couch: CouchDb) = {
  val db = couch.dbs.get(dbName)
  await(db) match {
    case -\/(e) =>
      println(s"Creating database $dbName")
      await(couch.dbs.create(dbName))

    case \/-(existingDb) =>
      println(s"Database with name $dbName already existed")
  }
}

I'm always happy to get suggestions for code improvement!

Comments