代码之家  ›  专栏  ›  技术社区  ›  Xolve

无法使用Flatmap调用bsonCollection.FindAndRemove()。

  •  2
  • Xolve  · 技术社区  · 7 年前

    reactiveMogo集合类型提供方法 findAndRemove 用于根据查询条件从集合中删除一个文档。它返回一个描述删除操作结果的未来。对未来的未来调用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]
    

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

    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: 呼叫地图工作:

    def remove = testColl.map(_.findAndRemove(BSONDocument("atomicNumber" -> 26)))
    println(await(await(remove)))
    
    1 回复  |  直到 7 年前
        1
  •  4
  •   Travis Brown    7 年前

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

    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]) 如果你想解码结果,等等。