6

私はこのようなクラスを持っています:

class Foo {
    static hasMany = [bars: Bar]
}

私が書くとき:

Foo.getAll()

Foo次のようなオブジェクトのリストを取得します。

[ Foo1, Foo2, Foo3 ]

私が書くとき:

Foo.getAll().bars

Bar次のようなオブジェクトのリストのリストを取得します。

[ [ Bar1, Bar2 ], [ Bar2, Bar3 ], [ Bar1, Bar4 ] ] 

Barしかし、私が欲しいのは、次のようなオブジェクトの一意のリストです。

[ Bar1, Bar2, Bar3, Bar4 ]

Bar私の最終目標は、次のように、上記のリストにあるオブジェクトのIDの一意のリストを作成することです。

[ 1, 2, 3, 4 ]

収集方法のバリエーションを試し、スプレッド演算子も試しましたが、うまくいきません。

4

3 に答える 3

8

一般的なGroovyクラス(つまり、非GORMクラス)の場合、Davidは、を使用するのが正しい方法flattenuniqueあり、これが最善の方法です。

ただし、この例では、GORMドメインオブジェクトを多対多の関係で使用しているように見えます(そうでない場合は、一意性の制約は必要ありません)。

ドメインクラスの場合、HQLまたは基準のいずれかを使用してこれを1つのステップで実行するのが最善です。追加の利点は、そのために生成されたSQLがはるかに効率的であることです。

多対多の関係にBarあるものに関連する一意のIDを取得するためのHQLは次のとおりです。Foo

Bar.executeQuery("select distinct b.id from Foo f join f.bars b")

このための基準は次のようになります。

Foo.withCriteria {
    bars {
        projections {
          distinct("id")
        }
    }
}

この種の方法を使用する際の「問題」の1つは、HQLが単体テストでサポートされていない(おそらくサポートされない)ことと、結合テーブルの射影を使用したCriteriaクエリが2.0.4の単体テストで壊れていることです。したがって、このコードに関するテストは、モックするか、統合テストを使用する必要があります。

于 2012-06-21T02:15:46.073 に答える
4

より良い方法があるかもしれませんが、フラットユニークなものを使用することができます。

何かのようなもの:

def allBars = Foo.getAll().bars.flatten().unique()

編集:
私はちょうど読み直して、あなたがバーではなく、最後にIDのリストの後にいることを確認しました。あなたが提案collect{ it.id }したように、IDを取得するために使用します。パフォーマンス上の理由から、リストを一意にする前にこれを行います。

于 2012-06-21T00:14:10.383 に答える
4

次にCollection#collectManyを呼び出すのと同じように機能するメソッドがあります。バーIDのリストを取得するには、次のようにします。collectflatten

def barIds = Foo.getAll().collectMany { it.bars*.id }

クロージャーは、Bars of a Fooの{ it.bars*.id }IDを含むリストを返し(私はこれらのプレースホルダー名が大好きです)、collectManyそれらのリストを1つのリストに連結します。IDを一意にする必要がある場合(おそらく、バーは複数のFooに属することができます)、.unique()その式にを追加できます:)

于 2012-06-21T00:26:49.563 に答える