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 {...}ブロックの各操作で右の予測、ベースまたは完全に洗練されていないクエリを実行する「失敗した」左の結果、および完全なドロップ+テイクの洗練を実行する成功した右の結果のいずれかを使用する傾向があります。

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(_,_) } }
}

これがコンパイルされる可能性は低いです;-)が、一般的な原則は、両方が顧客のリストを返す左/右のクエリ結果をスレッド化することです。

注:私はマッパーコンパニオンオブジェクトに複数形のケースクラスで名前を付ける傾向があるため、この場合、CustomerTableの代わりにCustomersを使用しました。また、次のようにCustomers.createFinder(_.id)脱糖します。

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

これは、基盤となるDBMS用の効率的なプリペアドステートメントを遅延生成します。

もちろん、あなたが持っているものは一回限りの場合にはうまく見えます。個人的に、私は{} +どちらの正しい予測でも、あなたのケーキを持ってそれを食べることができます-つまり、オプションを介した{...}とは対照的に、単一障害点の左の結果と成功した右の結果の両方を取得します、これは成功したイベントのみを生成し、どのステップが実際に失敗したかについての情報をまったく提供しません。

于 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 に答える