BSONCollection.findAndRemove() 无法使用平面图调用
BSONCollection.findAndRemove() cannot be called using flatmap
ReactiveMongo 集合类型提供方法findAndRemove,可用于根据查询条件从集合中删除一个文档。它 returns 描述删除操作结果的 Future。在这个 Future 的 Future 上调用 flatMap() 会导致一个相当神秘的错误消息:
type mismatch;
found : reactivemongo.api.collections.bson.BSONCollection => scala.concurrent.Future[x.BatchCommands.FindAndModifyCommand.FindAndModifyResult] forSome { val x: reactivemongo.api.collections.bson.BSONCollection }
required: reactivemongo.api.collections.bson.BSONCollection => scala.concurrent.Future[S]
我想这是我无法直接使用的内部 class 的结果类型。我无法理解我应该在这里做什么才能使用它。整个列表如下:
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.BatchCommands.FindAndModifyCommand.FindAndModifyResult] forSome { val x: 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)))
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])
,等等。
ReactiveMongo 集合类型提供方法findAndRemove,可用于根据查询条件从集合中删除一个文档。它 returns 描述删除操作结果的 Future。在这个 Future 的 Future 上调用 flatMap() 会导致一个相当神秘的错误消息:
type mismatch;
found : reactivemongo.api.collections.bson.BSONCollection => scala.concurrent.Future[x.BatchCommands.FindAndModifyCommand.FindAndModifyResult] forSome { val x: reactivemongo.api.collections.bson.BSONCollection }
required: reactivemongo.api.collections.bson.BSONCollection => scala.concurrent.Future[S]
我想这是我无法直接使用的内部 class 的结果类型。我无法理解我应该在这里做什么才能使用它。整个列表如下:
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.BatchCommands.FindAndModifyCommand.FindAndModifyResult] forSome { val x: 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)))
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])
,等等。