Squeryl - 查询组合的手段

时间:2012-11-22 15:02:32

标签: performance scala subquery squeryl

我需要通过REST接口执行一些可能依赖于外部提供的参数的查询。例如,客户可能需要表格

的URL
some/entities?foo=12&bar=17

参数,例如foobarquux都是可选的。所以我从使用Squeryl设计一些查询开始,比如

object Entity {
  def byFoo(id: Long) = from(DB.entities)(e =>
    where(e.foo === id)
    select(e)
  )
  // more criteria
}

但是我当然希望避免出现组合爆炸,所以我只设计了三个查询,而这些查询又可以从另一个查询中获取数据:

object Entity {
  def byFoo(id: Long, source: Query[Entity] = DB.entites) = from(source)(e =>
    where(e.foo === id)
    select(e)
  )
  def byBar(id: Long, source: Query[Entity] = DB.entites) = from(source)(e =>
    where(e.bar === id)
    select(e)
  )
  // more criteria
}

现在我可以将它们组合起来并运行像

这样的查询
val result = Entity.byFoo(12,
  source = Entity.byBar(17)
)

我采用这种方法的唯一问题是幕后的Squeryl将生成子查询,这可能是低效的。使用更典型的查询构建器,我将能够组合查询并获得以下内容的等效项:

from(DB.entities)(e =>
  where(
    e.foo === 12 and
    e.bar === 17
  )
  select(e)
)
  

是否有一种不同的方法可以动态组合Squeryl中的查询,从而形成更高效的表单?

1 个答案:

答案 0 :(得分:2)

我认为你应该考虑的第一件事就是抑制,你可以找到in the documentation。它的要点是您为查询建模,如:

var foo: Option[Int] = None
var bar: Option[Int] = None

from(DB.entities)(e =>
  where(
    e.foo === foo.? and
    e.bar === bar.?)
  select(e))

?第一个表达式中的运算符等价于(e.foo === foo).inhibitWhen(foo == None)