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?
我对如何仅使用 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?