mongo-scala-driver:获得结果

时间:2016-02-26 02:56:44

标签: mongodb-query mongo-scala-driver

我在Mongodb中有以下文档:

{ "index_column" : "site_id", "mapped_column":"site_name"}

我使用scala代码中的mongo-scala-driver来查询服务器。如何将mapped_column转换为scala String变量?我尝试使用以下代码:

val result = mongocollection.find(equal("index_column", data)).first()

返回org.mongodb.scala.ObservableImplicits$BoxedObservable@207c9b87 是否可以将Observable转换为Iterator?我只需要scala String变量中的mapped_column值。

3 个答案:

答案 0 :(得分:0)

我通过将驱动程序切换到mongodb casbah解决了这个问题,可以使用以下代码完成:

{{1}}

答案 1 :(得分:0)

Scala驱动程序是完全异步的,因此您可以订阅结果。最简单的方法是使用foreach:

val result = mongocollection.find(equal("index_column", data)).first()
result.foreach { value => ... }

另一种选择是将Observable转换为Future

Await.result(result.toFuture(), 3 seconds)

答案 2 :(得分:0)

这是一个可能的解决方案。创建一个新的ObserverIterator实例,并使用它订阅一个可观察对象,然后将其用作Iterator。

import org.mongodb.scala.{Observer, Subscription}

import scala.collection.mutable
import scala.concurrent.{Await, Promise}
import scala.concurrent.duration.Duration
import scala.util.Try
import scala.annotation.tailrec
import scala.concurrent.duration._

/**
  * An observer that can be used as an Iterator.
  * Attention: hasNext and next() are potentially blocking in case the buffer is empty
  *
  * @param batchSize Number of records to fetch in one batch
  * @param timeout Max duration to wait for the queue to fill up or to get an onComplete signal
  * @param period Duration to wait before checking if the queue is still empty or if an onComplete signal has been received
  * @param threshold Min amount of entries in the buffer below which a new batch should be queried
  * @tparam T
  */
class ObserverIterator[T](batchSize: Long = 500,
                      timeout: Duration = 15.seconds,
                      period: Duration = 100.millis,
                      threshold: Long = 100)
extends Observer[T]
with Iterator[T] {
  assert(threshold > 0)
  assert(batchSize > threshold)

  private val buffer = new mutable.Queue[T]()
  private var subscription: Option[Subscription] = None
  private var requestable = false

  override def onSubscribe(subscription: Subscription): Unit = {
    this.subscription = Some(subscription)
    subscription.request(batchSize)
  }

  override def onNext(t: T): Unit = {
    buffer.enqueue(t)
    if (buffer.size >= threshold)
      requestable = true
  }

  private val p = Promise[Unit]()
  private val f = p.future
  override def onComplete(): Unit = {
    p.success(())
    requestable = false
  }

  override def onError(e: Throwable): Unit = throw e

  //Blocking
  override def hasNext: Boolean = {
    if (requestable && buffer.size < threshold) {
      subscription.get.request(batchSize)
      requestable = false
    }
    @tailrec
    def hasNextImpl(cnt: Duration = timeout): Boolean = {
      if (buffer.nonEmpty)
        true
      else if (p.isCompleted)
        false
      else {
        if (cnt < 0.second)
          throw new Exception("hasNext timeout")
        else
          Try {
            Await.result(f, period)
          } match {
            case _ =>
              hasNextImpl(cnt - period)
          }
      }
    }
    hasNextImpl()
  }

  //Blocking
  override def next(): T = {
    if (hasNext)
      buffer.dequeue()
    else
      throw new Exception("Called next on empty Iterator")
  }
}