我用Play!使用ReactiveMongo插件的框架(相应版本2.3和0.11)。我有下一个代码从MongoDB集合中删除项目并返回一些受影响的项目:
/**
* Removes all subscribers by subscription id
*
* @param subscriptionId id of the subscription
* @return count of removed subscribers
*/
def deleteAll(subscriptionId: String): Future[Int] = {
logger.debug(s"Removing all subscribers with subscription id '$subscriptionId'...")
val query = BSONDocument("subscriptionId" -> BSONObjectID(subscriptionId))
subscribersCollection.remove(query) map { writeResult: WriteResult =>
writeResult.n match {
case subscribersRemoved if subscribersRemoved > 0 =>
logger.debug(s"Successfully removed $subscribersRemoved subscribers with subscribtion id '$subscriptionId'")
case _ => logger.debug(s"No subscribers with subscribtion id '$subscriptionId' were removed")
}
writeResult.n
}
}
由于ReactiveMongo文档,集合WriteResult
方法返回的remove()
类具有hasError
和writeErrors
等字段,用于指示执行期间发生的错误数据库查询。
那么,根据WriteResult
的{{1}}字段,为了从中返回失败,最好和最干净的方法是什么?
这是一个粗略的例子:
hasError
即。即使数据库查询返回带有错误字段的subscribersCollection.remove(query).??? match {
case Success(writeResult) if writeResult.hasErrors => Failure(new DatabaseException(writeResult.errMsg, writeResult.code)
case any => any
}
Failure
提前致谢!我真的很感激任何帮助,以使我的代码更好
P.S。我已经考虑将所有代码包装在Success
中,只是在设置为Try
的{{1}}标记上抛出异常,但我相信它可以以更好的方式完成,也许可以{ {1}} hasError
方法
P.P.S。出于某种原因,来自ReactiveMongo documentation的代码示例和演示不处理true
的错误字段和标记。事实上,文档说
如果写入结果实际指示错误,则Future将进入 失败的状态
但是,我已经在几个应用程序中看到了生产代码中的这种处理,所以它有点令人困惑。这是否意味着这种处理过度?
答案 0 :(得分:2)
使用flatMap
和Future.failed
在flatMap
上执行Future
,然后根据值Future.failed(new Exception("unexpected value"))
假设我们有一个返回某个int的未来的函数
def httpStatus: Future[Int] = Future { 404 }
httpStatus.flatMap {
case 404 => //return failed future
Future.failed(new Exception("Bad status"))
case value => value
}
现在您的代码变为
def deleteAll(subscriptionId: String): Future[Int] = {
logger.debug(s"Removing all subscribers with subscription id '$subscriptionId'...")
val query = BSONDocument("subscriptionId" -> BSONObjectID(subscriptionId))
subscribersCollection.remove(query) flatMap { writeResult: WriteResult =>
writeResult.n match {
case subscribersRemoved if subscribersRemoved > 0 =>
logger.debug(s"Successfully removed $subscribersRemoved subscribers with subscribtion id '$subscriptionId'")
Future.successful(writeResult.n)
case status =>
logger.debug(s"No subscribers with subscribtion id '$subscriptionId' were removed")
Future.failed(new Exception(s"bad status exception. status: $status"))
}
}
}