如何在未来打开选项?

时间:2016-09-16 17:36:36

标签: scala

我想实现一个创建用户的方法(如果用户尚不存在)。如果确实存在,则应返回用户。

这是我的代码:

<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 } 返回findOneByNameFuture[Option[User]]返回createUser所以类型不匹配。

如果有Future[User],如何将Future[Option[User]]解包给Future[User]或抛出异常?

3 个答案:

答案 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)))