Scala

ReactiveMongo: Work with array

reactive-mongo-logoI’ve been working with ReactiveMongo during 6 months. It’s pretty nice realisation of MongoDB driver for Scala. I just have one remark – it has not so good documentation as it should be. Especially bad documentation have MongoDB operators. Fortunately original MongoDB documentation fix this circumstance.

So in this tutorial I want to demonstrate how you can deal with JSON arrays. I’m going to examine $pull and $push operators. After the practical part of the post, I hope you will get answers on questions how to add element in array using ReactiveMongo (add / remove).

Let’s assume we have a model like this:

case class Person(_id: Option[BSONObjectID],
                  name: String,
                  phones: Option[Seq[String]])

object Person {
  implicit val personWrites: Writes[Person] = (
    (JsPath \ "_id").writeNullable[BSONObjectID] and
    (JsPath \ "name").write[String] and
    (JsPath \ "phones").writeNullable[Seq[String]]
  )(unlift(Person.unapply))

  implicit val personReads: Reads[Person] = (
    (JsPath \ "_id").readNullable[BSONObjectID].map(_.getOrElse(BSONObjectID.generate)).map(Some(_)) and
      (JsPath \ "name").read[String] and
      (JsPath \ "phones").readNullable[Seq[String]]
    )(Person.apply _)
}

As you see case class Person has “phones” field, which is represented by Seq[String]. Also it’s wrapped with Option, but it’s not so important. How we can implement operations of adding and deleting of elements from “phones” array? The answer is hidden in official MongoDB docs.

To implement “add to array” operation using ReactiveMongo, I need to:

def addPhone(name: String, phone: String) = {
    val newPhone = Json.obj(
      "$push" -> Json.obj(
        "phones" -> phone
      )
    )
    collection.update(
      Json.obj("name" -> name),
      newPhone
    )
  }

Pay your attention to “name” field. It have to be unique. Also you probably noticed Json object. It’s class from PlayFramework.

In order to delete some particular phone in “phones” array we need to:

def removePhone(name: String, phone: String) = {
    val phoneToDelete = Json.obj(
      "$pull" -> Json.obj(
        "phones" -> phone
      )
    )
    collection.update(
      Json.obj("name" -> name),
      phoneToDelete
    )
  }

I recommend to refer official MongoDB documentation each time when you don’t find something you want in ReactiveMongo docs. This approach works well for most cases.

Reference: ReactiveMongo: Work with array from our JCG partner Alexey Zvolinskiy at the Fruzenshtein’s notes blog.

Alexey Zvolinskiy

Alexey is a test developer with solid experience in automation of web-applications using Java, TestNG and Selenium. He is so much into QA that even after work he provides training courses for junior QA engineers.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button