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で追加された新コマンドです。