Scala:在内部编写查询以获得错误

时间:2017-01-17 03:46:52

标签: scala

我正在努力让这个查询正确但却出错。首先,searchUser返回一个匹配的UserEntries序列,其中包含用户的唯一ID,对于每个userId,还有第二个查询从另一个表中获取一些其他用户信息+地址。

代码:

def searchUsers(pattern: String) = auth.SecuredAction.async {
  implicit request =>
    usersService.searchUser(pattern) flatMap { usrList =>
      for {
        u <- usrList
        ui <- usersService.getUsersWithAddress(u.id)
      } yield {
        Ok(views.html.UserList(ui))
      }
    }
}

所用API的签名:

def searchUser(pattern: String): Future[Seq[UserEntry]] = ...    
def getUsersWithAddress(userId: Long): Future[Seq[(UserProfile, Seq[String])]] = ...

错误:

[error] modules/www/app/controllers/Dashboard.scala:68: type mismatch;
[error]  found   : scala.concurrent.Future[play.api.mvc.Result]
[error]  required: scala.collection.GenTraversableOnce[?]
[error]           ui <- usersService.getUsersWithAddress(u.id)
[error]              ^
[error] one error found
[error] (www/compile:compileIncremental) Compilation failed

如果我注释掉行“u&lt; - usrList”并对下一行的用户ID进行硬编码,例如“ui&lt; - usersService.getUsersWithAddress(1L)”就可以了。知道我错过了什么吗?

2 个答案:

答案 0 :(得分:1)

当您在for comprehension中使用多个生成器时,monad必须属于同一类型。例如。你不能:

scala> for{ x <- Some("hi"); y <- List(1,2,3) } yield (x,y)
<console>:11: error: type mismatch;
found   : List[(String, Int)]
required: Option[?]
          for{ x <- Some("hi"); y <- List(1,2,3) } yield (x,y)
                                  ^

您可以做的是将一个或另一个转换为匹配正确的类型。对于上面的例子,那将是:

scala> for{ x <- Some("hi").toSeq; y <- List(1,2,3) } yield (x,y)
res2: Seq[(String, Int)] = List((hi,1), (hi,2), (hi,3))

在您的特定情况下,您的一个生成器是GenTraversableOnce,另一个是Future。您可以使用Future.successful(theList)来获得两个期货。请参阅此处的答案:

Unable to use for comprehension to map over List within Future

答案 1 :(得分:0)

根据@Brian的回答得出一个解决方案..以下工作(无法输入格式化程序代码块作为注释 - 所以添加为答案):

  usersService.searchUser(pattern) flatMap { usrList =>
    val q = for {
      u <- usrList
    } yield (usersService.getUserWithAddress(u.id))
    val r = Future.sequence(q)
    r map { ps =>
      Ok(views.html.UserList(ps))
    } 
  }

为了理解,积累了Futures,然后将序列展平,然后进行映射。希望这就是它的完成方式!

注意:我还必须将getUserWithAddress的签名更改为X而不是Seq [X]