ReactiveMongo: Work with array
I’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.