0

Record/Squeryl を ORM フレームワークとして使用する liftweb アプリケーションがあります。ここに私のスキーマがあります:

object AppSchema extends Schema {
  import org.squeryl.dsl.OneToManyRelation

  val groups = table[Group]("groups")
  val domains = table[Domain]("domains")

  val groupToDomains =
    oneToManyRelation(groups, domains).
      via((g, d) => g.id === d.groupId)
}

object Group extends Group with MetaRecord[Group] with Loggable {

}

class Group extends Record[Group] with KeyedRecord[Long] with Loggable {
  override def meta = Group
  @Column(name = "id") override val idField = new LongField(this)
  val name = new StringField(this, 700, "")
  @Column(name = "date_added") val createdAt = new DateTimeField(this)

  lazy val domains: OneToMany[Domain] = AppSchema.groupToDomains.left(this)
}

object Domain extends Domain with MetaRecord[Domain] with Loggable {

}

class Domain extends Record[Domain] with KeyedRecord[Long] {
  override def meta = Domain

  @Column(name = "id") override val idField = new LongField(this)
  @Column(name = "group_id") val groupId = new LongField(this)
  val name = new StringField(this, 700, "")
  @Column(name = "date_added") val createdAt = new DateTimeField(this)

  lazy val group: ManyToOne[Group] = AppSchema.groupToDomains.right(this)  
}

グループ内のドメインをカウントする関数を実装しようとしています:

def countDomainsInGroup(group: Group): Long = {
  val l = from(AppSchema.domains)(d => where(d.groupId === group.id) compute(count()))
  println("Count domains: " + l.statement)
  l.single.measures
}

これにより、次の SQL が生成されます。

Select
  count(*) as c0
From
  domains domains1
Where
  (domains1.group_id = 45)

これですべて問題ありませんが、適切な WHERE ステートメントが定義された group.domains が既にあるため、ショートカットがあるはずです。しかし、私はこのようにそれを使用しようとすると:

def countDomainsInGroup(group: Group): Long = {
  val l = from(group.domains)(d => compute(count()))
  println("Count domains: " + l.statement)
  l.single.measures
}

次の SQL が生成されます。

Select
  count(*) as c0
From
  (Select
     domains8.name as domains8_name,
     domains8.id as domains8_id,
     domains8.group_id as domains8_group_id,
     domains8.date_added as domains8_date_added,
   From
     domains domains8
   Where
     (45 = domains8.group_id)
  )  q1

ご覧のとおり、ここでサブクエリが生成されますが、これは必要ありません。私は何を間違っていますか?

4

1 に答える 1

0

OneToMany / ManyToOne を詳しく見てみると、Query を拡張していることがわかります。これらは基本的に、主キーによって親または子に関連するすべてのオブジェクトを取得するクエリを実行するのに便利です。そのように見ると、表示される SQL は驚くべきものではありません。クエリの結果のカウントを求めています。Squeryl は、SQL を出力するときに意図的にかなりリテラルであるため、書き直しを気にせずに自分で最適化できます。サブクエリが最適でない場合、リレーションのカウントを計算しなければならない理由はありません。

于 2013-11-27T17:19:56.413 に答える