scala - 无法使用平面图调用 BSONCollection.findAndRemove()

标签 scala reactivemongo

ReactiveMongo集合类型提供方法findAndRemove它可用于根据查询条件从集合中删除一个文档。它返回一个 Future 描述删除操作的结果。在此 Future 的 Future 上调用 flatMap() 会导致一条相当神秘的错误消息:

type mismatch;
 found   : reactivemongo.api.collections.bson.BSONCollection => scala.concurrent.Future[x$5.BatchCommands.FindAndModifyCommand.FindAndModifyResult] forSome { val x$5: reactivemongo.api.collections.bson.BSONCollection }
 required: reactivemongo.api.collections.bson.BSONCollection => scala.concurrent.Future[S]

我猜这是一个内部类的结果类型,我不能直接使用。我无法理解我应该在这里做什么来使用它。整个 list 如下:

import reactivemongo.api.collections.bson.BSONCollection
import reactivemongo.api.{Cursor, DB, MongoConnection, MongoDriver}
import reactivemongo.bson.{BSONDocument, BSONDocumentReader, BSONDocumentWriter, Macros}

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.{Await, Future}
import scala.concurrent.duration._

object ReactiveMongoTest extends App {

  case class Element(symbol: String, atomicNumber: Long, atomicMass: Double)
  implicit val elementReader: BSONDocumentReader[Element] = Macros.reader[Element]
  implicit val elementWriter: BSONDocumentWriter[Element] = Macros.writer[Element]

  val elements = Seq(
    Element("Fe", 26, 55.845),
    Element("Co", 27, 58.933),
    Element("Ni", 28, 58.693)
  )

  def await[T](future: => Future[T]): T = Await.result(future, Duration.Inf)


  lazy val driver: MongoDriver = MongoDriver()
  lazy val conn: MongoConnection = driver.connection(Seq("localhost"))
  def testDb: Future[DB] = conn.database("testDb")
  def testColl: Future[BSONCollection] = testDb.map(_.collection("testColl"))

  def insert = testColl.flatMap(_.insert(ordered = true).many(elements))

  def list = testColl.flatMap {
    _.find(BSONDocument(), projection = Option.empty)
      .cursor[Element]()
      .collect[Seq](Int.MaxValue, Cursor.FailOnError[Seq[Element]]())
  }

  def remove = testColl.flatMap(_.findAndRemove(BSONDocument("atomicNumber" -> 26)))

  println(await(insert))

  await(list).foreach(x => println(s"listing -> ${x}"))

//  println(await(remove))

  println("After removing!")
  await(list).foreach(x => println(s"listing -> ${x}"))

  sys.exit()

}

错误消息是:

Error:(37, 48) type mismatch;
 found   : reactivemongo.api.collections.bson.BSONCollection => scala.concurrent.Future[x$4.BatchCommands.FindAndModifyCommand.FindAndModifyResult] forSome { val x$4: reactivemongo.api.collections.bson.BSONCollection }
 required: reactivemongo.api.collections.bson.BSONCollection => scala.concurrent.Future[S]
  def remove = testColl.flatMap(_.findAndRemove(BSONDocument("atomicNumber" -> 26)))

更新 1: 调用 map 的工作原理:

def remove = testColl.map(_.findAndRemove(BSONDocument("atomicNumber" -> 26)))
println(await(await(remove)))

最佳答案

ReactiveMongo 对于很多内部案例类等来说太聪明了,每次我不得不使用它时,我都会遇到这样的奇怪问题。您可以通过提供固定存在范围的类型注释来强制它进行编译:

scala> type FAMResult =
     |   c.BatchCommands.FindAndModifyCommand.FindAndModifyResult forSome {
     |     val c: BSONCollection
     |   }
defined type alias FAMResult

scala> def remove =
     |   testColl.flatMap[FAMResult](_.findAndRemove(BSONDocument("atomicNumber" -> 26)))
remove: scala.concurrent.Future[FAMResult]

不过,除非您不关心删除命令的结果,否则这可能并不理想。更好的方法是映射到 Future[<blah blah blah>.FindAndModifyResult] flatMap 内这样你最终会得到一个更有用的类型:

scala> def remove = testColl.flatMap(
     |   _.findAndRemove(BSONDocument("atomicNumber" -> 26)).map(_.value)
     | )
remove: scala.concurrent.Future[Option[reactivemongo.bson.BSONDocument]]

您也可以只是 .map(_ => ())如果你实际上不关心结果,.map(_.result[Element])如果你想要解码结果等。

关于scala - 无法使用平面图调用 BSONCollection.findAndRemove(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54650308/

相关文章:

scala - Symbol 是一个案例对象吗?

scala - 如何将Scala列表成对?

scala - REPL 返回 RDD 值,但 SBT 无法编译

scala - 如何将 Spark 中 `Dataframe` 的两列合并为一个 2 元组?

mongodb - 如何在 Scala/ReactiveMongo 中映射两个 `future` 结果?

sql - 每个请求播放 2 个事务

mongodb - ReactiveMongo:插入新文档时如何处理数据库错误

mongodb - 玩!添加reactivemongo插件后框架 Controller 返回EMPTY RESPONSE

mongodb - ( react 性)Mongo 测试失败,返回 : unrecognised field 'snapshot'

json - Play 2.1和reactivemongo 0.8计数文档