scala将光滑的结果保存到新对象中

时间:2017-05-09 12:49:04

标签: scala playframework playframework-2.0 slick

有没有办法将光滑的查询结果保存到新对象中?

这是我的光滑结果,只有一个"对象"在列表中

val result: Future[Seq[ProcessTemplatesModel]] = db.run(action)

结果应映射到ProcessTemplatesModel,因为我想访问像这样的值

process.title

这可能吗?

由于

1 个答案:

答案 0 :(得分:2)

TL; DR :您应该尽可能保留上下文。

Future表示该值将在未来的某个时间给出(这就是我所说的值的上下文)。

使用它的不好方法是阻止你的线程,直到找到这样的值,然后使用它。

更好的方法是告诉你的程序:“一旦找到值(无论何时),用它做点什么”。这是一个延续或回调,并在scala中使用mapflatMap实现。

Seq是您价值的另一个背景。这意味着您实际上有不同的可能值。如果您想确保最多只有一个值,则可以seq.headOption始终将上下文从Seq切换为Option

使用它的不好方法是取第一个值,而不用检查它是否存在。

更好的方法是告诉你的程序:“无论你有多少价值,都要为每个人做这件事”。

现在,你如何在上下文中工作?您使用Functor和/或Monad运算符:mapflatMap

例如,如果要将函数convertToSomethingElse应用于上下文的每个元素,只需执行

result.map(list => list.map(process => convertToSomethingElse(process))

你会得到Future[Seq[SomethingElse]]

另一个例子,如果你想将结果保存在其他地方,你可能会有一些IO或数据库操作,这可能需要一些时间,并且可能会失败。我们假设您有一个函数save(entity: ProcessTemplateModel): Future[Boolean],可以让您保存一个模型。函数将花费一些时间(并且它将在另一个线程中启动)并且可能失败的事实在返回类型Future[Boolean]中可见(Boolean在这里并不重要,这是我们的事实再次拥有重要的Future背景。

在这里,您必须这样做(假设您只想保存列表中的第一个元素):

val savedFirstResult: Future[Option[ProcessTemplatesModel]] = result.flatMap {list => 
  Future.traverse(list.headOption){ process =>  //traverse will switch the Future and Option contexts
    save(process)
  }
}

正如您所看到的,我们可以通过留在Slick返回的上下文中来完成我们想要的大部分内容。你不应该想要超越它们,因为

  • 大部分时间,没有必要,当你有map使用内部上下文时某些函数用于上下文之外的值
  • 提取方法大部分时间都是不安全的:如果Option#get中没有元素,Option会抛出异常,Await.result(future, duration)可能会阻止所有计算或抛出异常
  • Play中的回复!可以使用Future
  • 在控制器中以Action.async的形式提供