问题描述
给出类型为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中表达的搜索条件.因此,我认为奇怪的是,鉴于基本原理提供了获取SqlRow
的Stream
的方法,我没有找到在其上应用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的输出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!