AggregateSpecクラスを使うと、集計処理を行うことができます。集計には集合関数を使うので、オブジェクトをフェッチしてから計算するよりも高速に実行することができます。
AggregateSpecクラスは、SQLの集合関数とGROUP BY句、HAVING句にあたります(ただし、まだHAVINGの機能は使用できません)。AggregateSpecを使ってフェッチしたデータは、フレームワークでは管理されませんので注意してください。集計処理の最新の結果はその都度フェッチする必要があります。
AggregateSpecの使い方はFetchSpecと似ています。まず、集計に使うエンティティ名と検索条件、ソート順序を用意し、AggregateSpecオブジェクトを生成します。次に集計したい属性を使用する集合関数を指定してAggregateSpecオブジェクトに追加します。グループ化を行うなら、AggregateSpec#group()に
グループ化に使う属性名を指定します。
あとはFetchSpecと同様、EditingContext#fetch()
の引数にAggregateSpecオブジェクトを指定してフェッチします。結果はハッシュの配列で返ってきます。
AggregateSpecは以下の集計処理をサポートしています。
集計処理 | SQL関数 | 説明 |
---|---|---|
AggregateSpec::AVG |
AVG |
平均を求める |
AggregateSpec::MAX |
MAX |
最大値を求める |
AggregateSpec::MIN |
MIN |
最小値を求める |
AggregateSpec::SUM |
SUM |
合計を求める |
AggregateSpec::COUNT |
COUNT |
データの行数を求める。 |
AggregateSpec::COUNT_ALL |
COUNT(*) |
データの行数を求める。ただし、NULL 値の行も含む。 |
例として、Employee
エンティティから名前が"A"で始まる従業員の人数を調べます。ソートは必要ないので、エンティティ名と検索条件を与えてAggregateSpecオブジェクトを生成します。
qualifier = Qualifier.format("name like 'A*'") spec = AggregateSpec.new("Employee", qualifier)
次に、集計に使うname
属性を追加します。属性の追加には、集計結果を取得するためのキーと集計処理を指定します。ここでは"total
"というキーで集計結果を取得できるよう設定します。
spec.add("total", "name", AggregateSpec::COUNT)
以上でAggregateSpecの準備は終了です。最後にEditingContext#fetch()
で集計結果を取得します。
objects = ec.fetch(spec) puts objects #-> [{'total'=>...}]
cdエンティティから、アーティストごとのアルバム数を集計します。AggregateSpec#group()
にアーティスト名を指定し、アーティスト名でグループ化します。
spec = AggregateSpec.new('cd') spec.add('albums', 'title', AggregateSpec::COUNT) spec.group('artist') objects = ec.fetch(spec) puts objects #-> [{'artist'=>..., 'albums'=>...}]
ここで挙げた2つの例はサンプルコードを付属してありますので、参考にしてください。