ReactiveMongo 条件更新

ReactiveMongo conditional update

我对如何仅使用 futures 根据先前的查询有条件地更新文档感到困惑。

假设我想将某个值推送到文档中的数组中,前提是该数组的大小小于给定的整数。

我正在使用此功能来获取文档,在获取文档后我正在推送值 - 我无法做的是有条件地这样做。

def joinGroup(actionRequest: GroupRequests.GroupActionRequest): Future[GroupResponse.GroupActionCompleted] = {
//groupisNotFull() is a boolean future
groupIsNotFull(actionRequest.groupId).map(
  shouldUpdate => {
    if(shouldUpdate){
      Logger.info(actionRequest.initiator + " Joining Group: " + actionRequest.groupId)
      val selector = BSONDocument("group.groupid" -> BSONDocument("$eq" -> actionRequest.groupId))
      val modifier = BSONDocument("$push" -> BSONDocument("group.users" -> "test-user"))
      val updateResult = activeGroups.flatMap(_.update(selector, modifier))
        .map(res => {
          GroupActionCompleted(
            actionRequest.groupId,
            actionRequest.initiator,
            GroupConstants.Actions.JOIN,
            res.ok,
            GroupConstants.Messages.JOIN_SUCCESS
          )
        })
        .recover {
          case e: Throwable => GroupActionCompleted(
            actionRequest.groupId,
            actionRequest.initiator, GroupConstants.Actions.JOIN,
            success = false,
            GroupConstants.Messages.JOIN_FAIL
          )
        }
      updateResult
    }
    else {
      val updateResult = Future.successful(
       GroupActionCompleted(
          actionRequest.groupId,
          actionRequest.initiator,
          GroupConstants.Actions.JOIN,
          success = false,
          GroupConstants.Messages.JOIN_FAIL
        ))
      updateResult
    }
  }
)
}

 //returns a Future[Boolean] based on if there is room for another user.
private def groupIsNotFull(groupid: String): Future[Boolean] = {
findGroupByGroupId(groupid)
  .map(group => {
    if (group.isDefined) {
      val fGroup = group.get
      fGroup.group.users.size < fGroup.group.groupInformation.maxUsers
    } else {
      false
    }
  })

}

我很困惑为什么我不能这样做。编译错误为:

错误:类型不匹配; 发现:scala.concurrent.Future[response.group.GroupResponse.GroupActionCompleted] 要求:response.group.GroupResponse.GroupActionCompleted

对于 if 和 else 分支 'updateResult'。

作为附带问题..这是有条件地更新文档的正确方法吗 - 即查询它,执行一些逻辑然后执行另一个查询?

我认为问题是因为 joinGroup2 函数 return 类型是 Future[Response],而您 return 只是在 else 块中创建一个 Response。如果您查看 mapTo[T] 函数的签名,它 return 是一个 Future[T]。

我认为您需要将 Response 对象包装在 Future 中。像这样:

else {
  Future { Response(false, ERROR_REASON) }
}

顺便说一句,你有一个错字:Respose -> Response

好的,知道了 - 您需要 flatMap 第一个 Future[Boolean] 像这样:

groupIsNotFull(actionRequest.groupId).flatMap( ...

使用 flatMap,结果将是一个 Future[T],map 你将得到一个 Future[Future[T]]。编译器知道你想要 return 一个 Future[T] 所以它期望映射到 return 一个 T 而你正在尝试 return 一个 Future[T] - 所以它抛出错误.使用 flatMap 将解决这个问题。

在这里进一步阐明地图与平面地图:In Scala Akka futures, what is the difference between map and flatMap?