0

I've a Play controller Action that edits a document in MongoDB using ReactiveMongo. The code is shown below. Both name and keywords are optional. I'm creating a temp BSONDocument() and adding tuples to it based on if name and keywords exist are not empty. However, tmp is currently mutable(is a var). I'm wondering how I can get rid of the var.

    def editEntity(id: String, name: Option[String], keywords: Option[String]) = Action          {

    val objectId = new BSONObjectID(id)

    //TODO get rid of var here
    var tmp = BSONDocument()

    if (name.exists(_.trim.nonEmpty)) {
      tmp = tmp.add(("name" -> BSONString(name.get)))
    }

    val typedKeywords : Option[List[String]] = Utils.getKeywords(keywords)
    if (typedKeywords.exists(_.size > 0)) {
      tmp = tmp.add(("keywords" -> typedKeywords.get.map(x => BSONString(x))))
    }

    val modifier = BSONDocument("$set" -> tmp)
    val updateFuture = collection.update(BSONDocument("_id" -> objectId), modifier)
}

UPDATE After looking at the solution from @Vikas it came to me what if there are more (say 10 or 15) number of input Options that I need to deal with. Maybe a fold or reduce based solution will scale better?

Soumya Simanta
  • 11,523
  • 24
  • 106
  • 161

1 Answers1

1

In your current code you're adding an empty BSONDocument() if none of those if conditions matched? val modifier = BSONDocument("$set" -> tmp) will have an empty tmp if name was None and typedKeyWords was None. Assuming that's what you want here is one approach to get rid of transient var. also note having a var locally (in a method) isn't a bad thing (sure I'll still make that code look bit prettier)

 val typedKeywords : Option[List[String]] = Utils.getKeywords(keywords)
 val bsonDoc = (name,typedKeywords)  match{
  case (Some(n),Some(kw) ) => BSONDocument().add( "name" -> BSONString(n)) .add(("keywords" -> kw.map(x => BSONString(x))))
  case (Some(n), None) => BSONDocument().add( "name" -> BSONString(n))
  case (None,Some(kw)) => BSONDocument().add(("keywords" -> kw.map(x => BSONString(x))))
  case (None,None) => BSONDocument()

}
val modifier = BSONDocument("$set" -> bsonDoc)
Vikas Pandya
  • 1,998
  • 1
  • 15
  • 32
  • your solution will work and is certainly better than my initial solution. You are correct, if nothing has changed, there is no need to edit the document. I can just return. I'm wondering if a pattern match will scale to say 10 parameters? Maybe a foldLeft on a BSONDocument ? – Soumya Simanta Jun 06 '14 at 23:21