grails使用迭代gorm查询聚合的分页

时间:2013-06-23 12:04:58

标签: grails groovy gorm offset paginate

我有这个controller.method渲染与配置文件关联的所有内容,其中包含正确的偏移量和gsp中分页的最大值

    if (profil) {
        def max = params.max ? params.max as int : 5
        def offset = params.offset ? params.offset as int : 0
        List things = []

        things = Things.findAllByProfil(profil,[max: max, offset: offset, sort: 'dtCreated', order: 'desc'])
        [profil: profil, things: things, thingsCount: things.size()]
    }

但现在我有一个特殊的“聚合 - 配置文件”,它有一些关联的配置文件,我想把所有相关配置文件的所有内容放在一个列表中:

    if (profil) {
        def max = params.max ? params.max as int : 5
        def offset = params.offset ? params.offset as int : 0
        List things = []

        if(profil.typ == 'Aggregate'){
            List profiles = profil.profiles?.collect { Profil.collection.findOne(_id:it.id) }
            profiles.each() { pr ->
                if(pr) {
                    things+= Things.findAllByProfil(pr as Profil,[max: max,offset: offset,  sort: 'dtCreated', order: 'desc']) 
                }
            } 
            things.sort{a,b-> b.dtCreated<=>a.dtCreated}
        }else{

            things = Things.findAllByProfil(profil,[max: max, offset: offset, sort: 'dtCreated', order: 'desc'])
        }
        [profil: profil, things: things, thingsCount: things.size()]
    }

但是这种方式我使用offsetmax几次,对于每个关联的配置文件,所以结果列表太大了。

不幸的是结果设计应该保持不变,所以assert params.max == 5 && profil.typ == "Aggregate",第一页的结果是一个包含所有配置文件中最近5个内容的列表(因为我将它们全部放在一个列表中并排序它们可能是dtCreated)我的问题可能是:如何将相同的切片逻辑应用于聚合列表(以及如何以高效的方式聚合事物)

解决此问题的最佳方法是什么?

提前感谢任何提示

3 个答案:

答案 0 :(得分:2)

我认为这非常依赖于您希望如何在视图中显示结果。在聚合模式下,您有每个配置文件的事物数量的分页逻辑,但我想结果乘以相关配置文件的数量。因此,您需要对关联的配置文件的数量使用某种分页。

这就是我问你想如何显示你的结果的原因,因为这应该推动设计。

假设您处于聚合模式。 假设你有一个显示所有聚合配置文件的屏幕,到此为止你需要一个分页,目前你没有,然后如果用户点击每个配置文件向他们展示事物的结果,你需要另一个分页机制。

再次根据您的设计,您可能希望将“个人档案”列表与“事物”列表分开。对切​​片(分页)的结果采取不同的动作。在您目前的聚合模式设计中,问题是things.size() == profiles.count * max,您现在无法控制配置文件大小。

希望这个帮助

答案 1 :(得分:2)

首先,我想扩展一下rcgeorge23所说的内容,你最好让gorm /数据库处理你的聚合。 Section 6 of the Grails documentation会带你走很长的路。

在您的特定情况下,您可以简单地使用带有`findAllBy的内置比较器来处理聚合,这是一个具体的例子:

if(profil.typ == 'Aggregate'){
  List profiles = //some code to get a list of profiles
  def things = Things.findAllByProfilInList(profiles, [max: max....order: 'desc'])
} else {
  ...
}    

其次,你对分页的使用有点偏差。在技​​术上,thingsCount应该是符合条件的简单“选择计数”,但是您将返回受“max”限制的匹配条件。因此,对于thingsCount使用以下内容

def thingsCount = Things.countByProfilInList(profiles) //for all things with aProfile in list
 or
def thingsCount = Things.countByProfil(aProfile) //for all things with aProfile

答案 2 :(得分:1)

我认为理想情况下,您希望使用条件构建器,HQL或SQL或这些的某些组合来表达查询的profil.typ == 'Aggregate'位,这意味着您要让数据库完成工作而不是比你的申请。这也意味着maxoffset可以正常工作。

我不知道您的模型是什么样的,但我认为您可以通过在sqlRestriction块内使用SQL子选择来执行您想要的操作。很难在网上找到非平凡的例子,但文档here将帮助您入门。