【问题标题】:grails Pagination using iterative gorm querys aggregation使用迭代 gorm 查询聚合的 grails 分页
【发布时间】:2013-06-23 12:04:57
【问题描述】:

我有这个 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 &amp;&amp; profil.typ == "Aggregate",第一页的结果是一个包含所有配置文件的 5 个最新内容的列表(因为我将它们全部放在一个列表中并按dtCreated)和我的问题可能是:如何将相同的切片逻辑应用于聚合列表(以及如何以高效的方式聚合事物)

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

任何提示提前谢谢

【问题讨论】:

  • 您可以发布您的个人资料域吗?

标签: grails groovy grails-orm offset pagination


【解决方案1】:

首先,我想扩展一下 rcgeorge23 ​​所说的,让 gorm/database 处理您的聚合确实更好。 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 在技术上应该是一个与您的条件匹配的简单“选择计数”,但您返回的匹配条件受“最大值”限制。所以使用以下的 thingsCount

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

【讨论】:

  • 嘿,非常感谢“InList”比较器是我一直在寻找的完美解决方案,感谢“thingsCount”的提示,我可能会纠正你,我使用了 Things.countBy...
  • 你说得对,我有点高兴。我会更新的。
【解决方案2】:

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

这就是为什么我要问你想如何显示你的结果,因为这应该驱动设计。

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

再次根据您的设计,您可能希望将配置文件列表与其事物列表分开。用不同的动作来对你的结果进行切片(分页)。在您当前的聚合模式设计中,问题是things.size() == profiles.count * max,您现在无法控制配置文件的大小。

希望对你有所帮助

【讨论】:

  • 非常感谢,这确实有助于表达我需要做的事情,不幸的是结果设计应该保持不变,所以断言 params.max == 5 && profile.typ == "Aggregate",第一页的结果是一个包含所有配置文件的 5 个最新内容的列表(因为我将它们全部放在一个列表中并按 dtCreated 对其进行排序),我的问题可能是:如何将相同的切片逻辑应用于聚合列表(以及如何以高效的方式聚合事物)
【解决方案3】:

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

我不知道您的模型是什么样的,但我认为您可以通过在 sqlRestriction 块中使用 SQL 子选择来做您想做的事情。在网上很难找到重要的示例,但文档here 将帮助您入门。

【讨论】:

    猜你喜欢
    • 2011-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-05
    • 2011-10-09
    • 2017-03-19
    • 2021-07-30
    相关资源
    最近更新 更多