我有一个这样的课程:
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 ]
我尝试了collect方法的各种变体,我也试过spread operator,但我没有运气。
答案 0 :(得分:8)
对于通用的groovy类(即非GORM类),David认为使用flatten
和unique
是最好的方法是正确的。
在您的示例中,看起来您在多对多关系中使用GORM域对象(否则您不需要唯一性约束)。
对于域类,您最好使用HQL或条件一步完成此操作。另一个优点是为它生成的SQL效率更高。
这是用于获取与多对多关系中的任何Bar
相关的唯一Foo
ID的HQL:
Bar.executeQuery("select distinct b.id from Foo f join f.bars b")
这个标准如下:
Foo.withCriteria {
bars {
projections {
distinct("id")
}
}
}
一个"问题"使用这种方法的方法是单元测试(可能永远不会)和Criteria queries with join table projections are broken in 2.0.4 unit tests不支持HQL。因此,围绕此代码的任何测试都需要进行模拟或使用集成测试。
答案 1 :(得分:4)
可能有更好的方法,但您可以使用flatten和unique。
类似的东西:
def allBars = Foo.getAll().bars.flatten().unique()
编辑:
我刚刚重新阅读,看到你最后是一个ID列表,而不是Bars。如您所建议,您将使用collect{ it.id }
来获取ID。出于性能原因,我会在列表唯一之前这样做。
答案 2 :(得分:4)
有Collection#collectMany
方法与调用collect
然后调用flatten
的方法相同。要获取条形码ID列表,您可以执行以下操作:
def barIds = Foo.getAll().collectMany { it.bars*.id }
{ it.bars*.id }
闭包返回一个列表,其中包含一个Foo的Bars的ID(我喜欢这些占位符名称hehe),然后collectMany
将这些列表连接成一个列表。如果您需要ID是唯一的(可能Bar可以属于多个Foo),您可以在该表达式中添加.unique()
:)