我想实现一个创建用户的方法(如果用户尚不存在)。如果确实存在,则应返回用户。
这是我的代码:
<requestHandler name="/select" class="solr.SearchHandler">
<lst name="defaults">
<str name="defType">dismax</str>
<str name="qf">title^10 content^5</str>
</lst>
</requestHandler>
我的问题是def createUserIfNotExists(user: User) = {
for {
count <- userService.count(Some(user))
user <- if (count == 0) createUser(user) else userService.findOneByName(user.name)
} yield user
}
返回findOneByName
而Future[Option[User]]
返回createUser
所以类型不匹配。
如果有Future[User]
,如何将Future[Option[User]]
解包给Future[User]
或抛出异常?
答案 0 :(得分:2)
只需map
createUser
函数返回类型:
if (count == 0) createUser(user).map(Option(_)) else userService.findOneByName(user.name)
findOneByName
的返回类型包含Option
这一事实表明您可能没有用户。这种类型存在是有原因的,所以把它扔掉是很糟糕的,因为它丢弃了信息。
答案 1 :(得分:2)
make createUser
也会返回Future[Option[_]]
def createUserIfNotExists(user: User) = {
for {
count <- userService.count(Some(user))
userOpt <- if (count == 0) createUser(user).map(Some(_)) else userService.findOneByName(user.name)
} yield userOpt
}
或强>
您可以对该选项执行.get
,因为如果count不为零,则意味着用户在数据库中绝对可用。
def createUserIfNotExists(user: User) = {
for {
count <- userService.count(Some(user))
user <- if (count == 0) createUser(user) else userService.findOneByName(user.name).map(_.get)
} yield user
}
或强>
如果没有创建用户,首先尝试检索用户
def createUserIfNotExists(user: User) = {
for {
userOpt <- userService.findOneByName(user.name)
user <- userOpt match {
case Some(value) => value
case None => createUser(user).map(_ => user)
}
} yield user
}
请注意,为了确保并行数据库操作的正确性,强烈建议在transaction
答案 2 :(得分:1)
直接使用findOneByName
功能,这样您就不必再查询数据库两次了:
val res: Future[UserDB] =
userService
.findOneByName(user.name)
// if the option in the future is not empty, return its content
// otherwise create a new user
.flatMap(_.map(Future.successful).getOrElse(createUser(user)))