Scala 用于理解 Slick Query

Posted

技术标签:

【中文标题】Scala 用于理解 Slick Query【英文标题】:Scala for comprehension for Slick Query 【发布时间】:2015-08-10 11:37:29 【问题描述】:

我是 Scala 新手,我正在构建一个 Play 应用程序来学习 Scala 和 Slick。该应用程序有待办事项列表,每个列表都有项目。每个用户都有多个列表。我编写了一个控制器来获取 JSON 格式的列表,并且 JSON 包含列表中的所有项目。

  def viewList(id: Long) = AuthenticatedAction.async  implicit request =>
    val userId = request.user.toLong;
    db.run(todoLists.filter(listById(id, userId)).result.headOption).flatMap  list =>
      list match 
        case Some(_) => 
          val json = toJson(list).as[JsObject]
          // Fetch the items in this list and add them to the JSON response
          db.run(todoItems.filter(_.listId === id).sortBy(_.text).result).map  items => 
            Ok(json + ("items" -> toJson(items)))
          
        
        case None => Future.successful(NotFound)
      
    
  

是否可以使用 for 理解来编写此函数?我有一个嵌套的 flatMap+map 调用,所以看起来应该是可能的。

【问题讨论】:

每次调用 map、flatMap、filter 都可以重写为理解,但你真的需要吗?这可能更冗长 这是一个很好的问题 - 我是 Scala 新手,所以我不太清楚。有人告诉我,理解可以使事情更容易阅读。 如果你理解高阶函数的代码,我想你不会。可能只是为了练习或让其他人更好地理解,恕我直言 【参考方案1】:

是的,这是可能的。像这样:

def viewList(id: Long) = AuthenticatedAction.async  implicit request =>
  val userId = request.user.toLong
  for 
    list <- db.run(todoLists.filter(listById(id, userId)).result.headOption)
    resp <- list.fold[Future[Result]](Future.successful(NotFound))  _ =>
      val json = toJson(list).as[JsObject]
      // Fetch the items in this list and add them to the JSON response
      db.run(todoItems.filter(_.listId === id).sortBy(_.text).result).map  items => 
        Ok(json + ("items" -> toJson(items)))
      
    
   yield resp 

另一种变体:

  def viewList(id: Long) = AuthenticatedAction.async  implicit request =>
    val userId = request.user.toLong
    for 
      list <- db.run(todoLists.filter(listById(id, userId)).result.headOption)
      items <- db.run(todoItems.filter(_.listId === id).sortBy(_.text).result)
     yield list match 
      case Some(_) => Ok(toJson(list).as[JsObject] + ("items" -> toJson(items)))
      case None => NotFound
    
  

【讨论】:

感谢您的回答。我很困惑为什么我现在不需要第一次打电话给db.run。另外,是否可以在理解中包含剩余的 map 调用?我尝试将您重写的函数添加到我的代码中,但出现编译错误:Controller.scala:79: type mismatch; [错误] 找到:play.api.mvc.Result [错误] 必需:TodoListController.this.Status [错误] 好的(json +(“items”-> toJson(items))) 哦,抱歉,您需要 db.run。 我添加了对db.run的调用,但我仍然收到类型不匹配编译错误 完整的编译错误在上面的评论中。第 79 行是 Ok 所在的行。我不明白为什么现在需要的类型是状态。我意识到孤立地调试可能很困难。我的完整项目位于:bitbucket.org/thelateperseus/todo-play-angular/src/… [Future[Result]] 是必需的。我还添加了另一个变体,例如。

以上是关于Scala 用于理解 Slick Query的主要内容,如果未能解决你的问题,请参考以下文章

Scala Slick 无法将查询与计数联合起来

Scala Slick 将 Rep 子查询组合成一个 re

Scala Slick 3 游戏框架

Scala / slick:如果不存在则获取插入的行的ID

scala中的println用于理解

浅谈Slick- Slick101:第一个动手尝试的项目