I am writing a simple blog on Play Framework and MongoDB using Scala driver. So it works and I'm happy but feel like my code is not good enough. Could you guys review the following snippet which is one of my mongo service methods and tell me if there is a way to make it more clean:
def findByTitle(title:String)(implicit ec:ExecutionContext):Future[Option[Document]] = {
val collection = db.getCollection("items")
val results = collection.find(equal("title", title))
val contentPromise: Promise[Option[Document]] = Promise()
results.subscribe(new Observer[scala.Document] {
var empty: Boolean = true
override def onError(e: Throwable): Unit = println("Error")
override def onComplete(): Unit = {
if (empty) contentPromise.success(None)
}
override def onNext(result: scala.Document): Unit = {
empty = false
contentPromise.success(Some(result))
}
})
contentPromise.future
}
I decided to return Future[Option[Document]]
since there could be a chance that there is nothing by provided title. As far as the only way to work with Observable
is via Observer
callbacks I need to declare a Promise
and then fulfill that promise in the onComplete()
callback. To handle the case when there is no document by provided title I have no choice other than declaring this var empty: Boolean = true
variable and then using it in onNext()
and onComplete()
callbacks.
Question: Is there a better way to approach this without using var
inside my Observer
instance?
I think it would be far easier to work with a Future[T]
instead of an observable:
import org.mongodb.scala.ObservableImplicits._
def findByTitle(title: String)(implicit ec: ExecutionContext): Future[Option[Document]] = {
val collection = db.getCollection("it")
collection.find(equal("title", title))
.toFuture()
.recoverWith { case e: Throwable => { Log(e); Future.failed(e) } }
.map(_.headOption)
}
The T
in the future is actually a Seq[T]
. This way a simple check can eliminate the need for mutable state.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With