使用Play Framework 2中的Reactivemongo读取整个集合的奇怪行为

时间:2013-07-13 10:30:28

标签: mongodb scala playframework-2.0 reactivemongo

我有以下代码:

  def all: String = {

    val query = BSONDocument("name" -> BSONDocument("$ne" -> "allDocs"))

    val cursor = carsCollection.find(query).cursor[BSONDocument]
    Logger.debug("Before cursor")
    cursor.enumerate.apply(Iteratee.foreach {
      doc =>
        Logger.debug("found document: " + doc.getAs[BSONString]("name").get.value)
        //Logger.debug("found document: " + doc.getAs[BSONString]("area").get.value)
    })
    "Ok"
  }

当我运行此代码时,播放控制台会显示来自"name"的12个不​​同文档的字段mongodb。当我取消注释第二个Logger调用时,系统只打印一个名称并停止。数据库中存在"area"字段没有问题。

我做错了吗?

1 个答案:

答案 0 :(得分:1)

我的猜测是doc.getAs[BSONString]("area").get.value引发了一些异常。

您应该测试是否存在值以及值的类型以确定:

cursor.enumerate.apply(Iteratee.foreach { doc =>
  // ...
  doc.getAs[BSONString]("area") match {
    case Some(BSONString(area)) => Logger.debug(s"area is BSONString of value = $area")
    case None => Logger.debug("area does not exist or is not a BSONString"
  }
}

getAs[BSONString]方法返回Option[BSONString]。如果有值,但是这个值无法解析为BSONString - 换句话说,当值不是BSONString而是BSONInteger,BSONLong,BSONDocument等时 - 那么None退回。由于您在其上调用get,而不检查该选项是否已定义,因此可能会抛出NoSuchElementException

另一种方法:

cursor.enumerate.apply(Iteratee.foreach { doc =>
  // ...
  doc.get("area") match {
    case Some(BSONString(area)) => Logger.debug(s"area is a BSONString of value = $area")
    case Some(otherBSONValue) => Logger.debug(s"area exists but is not a BSONString: $otherBSONValue")
    case None => Logger.debug("area does not exist or is not a BSONString"
  }
}

如果您的iteratee中存在异常,则最终的未来可能会出错。

val future = cursor.enumerate |>>> Iteratee.foreach { doc =>
  Logger.debug("found document: " + doc.getAs[BSONString]("name").get.value)
  Logger.debug("found document: " + doc.getAs[BSONString]("area").get.value)
}
future.onComplete {
  case Success(_) => Logger.debug("successful!")
  case Failure(e) => Logger.debug(s"there was an exception! ${e.getMessage}")
}