在Play 2.6中将多个地图功能应用于流式数据库结果

时间:2018-08-01 06:53:00

标签: scala akka-stream anorm

我有一个大型查询,似乎是streaming results的主要候选人。

我想调用一个函数,该函数返回一个对象,可以在其上应用其他映射转换,然后最终将整个结果转换为一个列表。这是因为转换将导致一组对象比数据库中的结果小得多,并且必须顺序进行许多不同的转换。一次处理每个结果将为我节省大量内存。

例如,如果数据库的结果是一个流(尽管正确的东西很可能是AkkaStream或Iteratee),那么我可以做类似的事情:

def outer(converter1[String, Int}, converter2[Int,Double]) { 
    val sqlIterator = getSqlIterator()
    val mappedIterator1 = sqlIterator.map(x => converter1(x.bigColumn))
    val mappedIterator2 = sqlIterator.map(x => converter2(x))
    val retVal = mappedIterator.toList
    retVal
}

def getSqlIterator() {
   val selectedObjects = SQL( """SELECT * FROM table""").map { x => 
       val id = x[Long]("id")
       val tinyColumn = x[String]("tiny_column")
       val bigColumn = x[String]("big_column")

       NewObject(id, tinyColumn, bigColumn)
   } 

   val transformed = UNKNOWN_FUNCTION(selectedObjects)
   transformed
}

大多数文档似乎都提供了对结果应用“ reduce”功能而不是“ map”功能的机制,但是生成的映射功能将小得多,从而为我节省了大量内存。我应该为UNKNOWN_FUNCTION做些什么?

1 个答案:

答案 0 :(得分:0)

下面是一个简单的示例,该示例使用Anorm的Akka Streams支持从类型为String的单个列中读取值,对每个元素进行两次转换,然后将结果放入Seq中。如果需要的话,我将保留它作为练习,让您一次从多个列中检索值。

import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.Sink

import anorm._

import scala.collection.immutable.Seq
import scala.concurrent.Future

implicit val system = ActorSystem("MySystem")
implicit val materializer = ActorMaterializer()
implicit val ec = system.dispatcher

val convertStringToInt: String => Int = ???
val convertIntToDouble: Int => Double = ???

val result: Future[Seq[Double]] =
  AkkaStream.source(SQL"SELECT big_column FROM table", SqlParser.scalar[String])
    .map(convertStringToInt)
    .map(convertIntToDouble)
    .runWith(Sink.seq[Double])