本文介绍了是否有一种简单的方法来获取Stream作为RowParser的输出?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出类型为RowParser[Photo]rowParser,这是根据到目前为止我看到的代码示例解析来自表photo的行的列表的方式:

Given rowParser of type RowParser[Photo], this is how you would parse a list of rows coming from a table photo, according to the code samples I have seen so far:

def getPhotos(album: Album): List[Photo] = DB.withConnection { implicit c =>
  SQL("select * from photo where album = {album}").on(
    'album -> album.id
  ).as(rowParser *)
}

*运算符在其中创建类型为ResultSetParser[List[Photo]]的解析器.现在,我想知道是否有可能获得一个生成Stream的解析器(认为懒惰总是更好),但是我只想出了这一点:

Where the * operator creates a parser of type ResultSetParser[List[Photo]]. Now, I was wondering if it was equally possible to get a parser that yields a Stream (thinking that being more lazy is always better), but I only came up with this:

def getPhotos(album: Album): Stream[Photo] = DB.withConnection { implicit c =>
  SQL("select * from photo where album = {album}").on(
    'album -> album.id
  )() collect (rowParser(_) match { case Success(photo) => photo })
}

它有效,但似乎过于复杂.我当然可以在从第一个函数获得的List上调用toStream,但是我的目标是仅将rowParser应用于实际读取的行.有没有更简单的方法可以做到这一点?

It works, but it seems overly complicated. I could of course just call toStream on the List I get from the first function, but my goal was to only apply rowParser on rows that are actually read. Is there an easier way to achieve this?

如果事先知道感兴趣的行数,我知道在查询中应该使用limit.我还知道,在许多情况下,无论如何您都将使用整个结果,因此懒惰不会提高性能.但是在某些情况下,您可以节省几个周期,例如如果由于某种原因,您具有无法或不希望在SQL中表达的搜索条件.因此,我认为奇怪的是,鉴于基本原理提供了获取SqlRowStream的方法,我没有找到在其上应用RowParser的直接方法.

I know that limit should be used in the query, if the number of rows of interest is known beforehand. I am also aware that, in many cases, you are going to use the whole result anyway, so being lazy will not improve performance. But there might be a case where you save a few cycles, e.g. if for some reason, you have search criteria that you cannot or do not want to express in SQL. So I thought it was odd that, given the fact that anorm provides a way to obtain a Stream of SqlRow, I didn't find a straightforward way to apply a RowParser on that.

推荐答案

我最终创建了自己的与list方法相对应的stream方法:

I ended up creating my own stream method which corresponds to the list method:

def stream[A](p: RowParser[A]) = new ResultSetParser[Stream[A]]  {
      def apply(rows: SqlParser.ResultSet): SqlResult[Stream[A]] = rows.headOption.map(p(_)) match {
        case None => Success(Stream.empty[A])
        case Some(Success(a)) => {
          val s: Stream[A] = a #:: rows.tail.flatMap(r => p(r) match {
            case Success(r) => Some(r)
            case _ => None
          })

          Success(s)
        }
        case Some(Error(msg)) => Error(msg)
      }
   }

请注意,播放SqlResult只能是成功/错误,而每一行也可以是成功/错误.假设其余的相同,我只会在第一行中处理.这可能对您不起作用.

Note that the Play SqlResult can only be either Success/Error while each row can also be Success/Error. I handle this for the first row only, assuming the rest will be the same. This may or may not work for you.

这篇关于是否有一种简单的方法来获取Stream作为RowParser的输出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 15:51