MongoDB scala驱动程序:使用Observer回调时返回Future的最佳方法是什么?

时间:2016-07-16 21:23:29

标签: mongodb scala playframework

我正在使用Scala驱动程序在Play Framework和MongoDB上编写一个简单的博客。 所以它有效,我很高兴,但感觉我的代码不够好。 你们可以回顾下面的片段,这是我的mongo服务方法之一,并告诉我是否有办法让它更干净:

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
  }

我决定返回Future[Option[Document]]因为提供的标题可能没有任何内容。至于使用Observable的唯一方法是通过Observer回调,我需要声明Promise,然后在onComplete()回调中履行该承诺。为了处理没有提供标题的文档的情况,我除了声明这个var empty: Boolean = true变量,然后在onNext()onComplete()回调中使用它外别无选择。

问题:如果不在我的var实例中使用Observer,是否有更好的方法来解决此问题?

1 个答案:

答案 0 :(得分:15)

我认为使用Future[T]代替可观察对象要容易得多:

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)
}

将来T实际上是Seq[T]。这样一个简单的检查可以消除对可变状态的需要。