1

我有一个查询,我有条件地根据计数和偏移参数的存在与否进行增强。

val retrieveCustomer: (Option[String], Option[Int], Option[Int]) => List[Customer] = { ( customerId : Option[String], count : Option[Int], offset : Option[Int] ) =>
    val initialQ: Query[CustomerTable.type, Customer] = customerId.map( c => CustomerTable.where(_.id === c) ).getOrElse( CustomerTable.map { c => c } )
    val qPlusOffset = offset.map ( offset => initialQ.drop(offset) ).getOrElse(initialQ)
    val qoPlusLimit = count.map( count => qPlusOffset.take(count) ).getOrElse(qPlusOffset)

    DBGlobal.db.withTransaction { qoPlusLimit.list }

}

与这种方法相比,我很好奇是否有更简洁的方法来编写此方法。

请说。

4

2 回答 2

2

写这个有什么意义?

val retrieveCustomer: (Option[String], Option[Int], Option[Int]) => List[Customer] = { ( customerId : Option[String], count : Option[Int], offset : Option[Int] )

当你可以写这样的东西时:

def getCustomer(id: String, count: Option[Int], offset: Option[Int]): List[Customer]

这显然更简洁,尽管可能与您所追求的简洁无关。我倾向于在 for{...} 块中的每个操作上使用 Either Right 投影,“失败”Left 结果执行基本或非完全优化的查询,成功的 Right 结果执行完全 drop + take 改进.

def getCustomer(id: String, count: Option[Int], offset: Option[Int]): List[Customer] = { 
    val base = Customers.createFinder(_.id)
    val q = for{
      cust    <- base(id) toRight( List[Customer]() )
      dropped <- cust.drop(offset) toRight(cust)
      taken   <- dropped.take(count) toRight(dropped)
    } yield taken
    DBGlobal.db.withTransaction { q.list map { _.fold(_,_) } }
}

这不太可能编译;-),但一般原则是遍历左/右查询结果,它们都返回客户列表。

注意:我倾向于以 case class 的复数形式命名映射器伴生对象,因此在这种情况下,我使用了 Customer,而不是 CustomerTable。此外,Customers.createFinder(_.id)脱糖:

for{
  id <- Parameters[String]
  c  <- Customers if c.id is id
} yield c

它懒惰地为底层 DBMS 生成一个有效的准备好的语句。

当然,您所拥有的作品对于一次性案例来说看起来不错。就个人而言,我正在挖掘{} + 任何一个正确的预测,都可以吃掉你的蛋糕 - 即同时获得失败点的左结果和成功的右结果,而不是通过选项 for{...} ,它只产生一个成功的事件,根本不提供关于哪个步骤实际出错的信息。

于 2012-06-27T11:34:02.837 回答
0

这是一个班轮。

val qFinal = initialQ.drop(offset.getOrElse(0)).take(count.getOrElse(Int.MaxValue))
于 2012-07-08T15:48:05.517 回答