collection.distinct()およびentitySelection.distinct()は,オブジェクトの集合に対して使用できるDISTINCT VALUESのようなものです。
値を集積したい属性またはプロパティのパスはドット記法で記述します。このパスが間違っていると,正しい値が返されません。
たとえば,obj
というオブジェクト型フィールドのprop
というプロパティからdistinct()
を取り出したい場合を考えましょう。
$values:=ds.Table_1.all().distinct("obj") //#1
$values:=ds.Table_1.all().distinct("obj.prop") //#2
#1のobj
というパスはオブジェクト型のフィールド自体を指します。
#2のobj.prop
という属性パスは,リレーション属性obj
でリンクされたデータクラスのprop
プロパティ,あるいはオブジェクト型のストレージ属性obj
内部のprop
プロパティを指します。しかし,ドキュメントに明記されているように,リレートされた属性をdistinct()
で参照することはできません。obj.prop
はストレージ属性なので,一見,シンタックスには問題がないように思われます。実際,obj.prop
がスカラー値であれば,正しいコレクションが返されます。また,obj.prop.value
のようにオブジェクト内部のスカラー値プロパティまでパスを延長すれば,やはり正しいコレクションが返されます。しかし,obj.prop
がオブジェクト型の場合,distinct()
は空のコレクションを返します。
entitySelection.distinct()
がサポートしていない属性パス,つまり
- リレーション属性のスカラー値
- ストレージ属性のオブジェクト型
は,プロジェクションとcollection.distinct()
で取り出すことができます。
$values:=ds.Table_1.all().obj.distinct("prop")
obj
がdistinct()
のパス名ではなく,ORDAのパス名に含まれているのがポイントです。
ORDAでは,クラシック言語の自動リレーションの代わりにプロジェクションを使用し,リレーション先を参照するクエリを実行したり,逆にクエリからリレーション先のデータを参照したりすることができます。
エンティティセレクションをオブジェクト記法で発展させた場合,パスがリレーション名であればプロジェクションはエンティティセレクションを返しますが,パスがフィールド名であればコレクションを返します。つまり,ORDAのオブジェクト記法にはRELATE MANY SELECTION
やRELATE ONE SELECTION
だけでなくSELECTION TO ARRAY
のような働きもあるということです。
複数の属性からコレクションを作成したい場合はentitySelection.toCollection()
やentitySelection.extract()
を使用することができます。
entitySelection.extract()
はcollection.extract()
に似ていますが,v19で追加された新コマンドです。