【问题标题】:Search records bases on latest record in a hasmany relationship根据hasman关系中的最新记录搜索记录
【发布时间】:2014-04-24 07:31:09
【问题描述】:

我有两个域

class DomainA {
    String name
    Date dateCreated
    Date lastUpdated

    static transients = ['email']

    static hasMany = [domainBs: DomainB]

    public String getEmail() {
        DomainB.mostRecentRecord(this).get()?.email
    }
}

class DomainB {
    String email
    Date dateCreated
    Date lastUpdated

    static belongsTo = [domainA: DomainA]

    static namedQueries = {
        mostRecentRecord { domainA ->
            eq 'domainA', domainA
            order('dateCreated', 'desc')
            maxResults(1)
        }
    }
}

我的要求是获取名称以“M”开头的所有 DomainA 的列表,并且最新的 domainBs 记录在其电子邮件属性中包含 gmail。

我尝试了createCriteriahql,但没有得到想要的结果,可能是我做错了什么。

以下是我当前的代码

List<DomainA> listA = DomainA.findAllByNameIlike("M%")
List<DomainB> listB = []
listA.each { entity ->
    DomainB domainB = DomainB.mostRecentRecord(entity).get()
    if (domainB && (domainB.email.contains('gmail'))) {
        listB.add(domainB)
    }
}

但它不允许分页和排序。

有人可以使用createCriteriahql 或任何其他方式获取名称以“M”开头的所有DomainA 并且最新的domainB 在其电子邮件属性中包含gmail 的列表。

【问题讨论】:

    标签: grails grails-domain-class grails-2.3


    【解决方案1】:

    由于您要查找最近的电子邮件,因此您需要查看 secondDomain 上的最大 dateCreated。您可以使用 HQL 编写它并使用 executeQuery 来传递您的分页参数。只要确保在您的dateCreated 上有一个索引。

    FirstDomain.executeQuery("select fd from FirstDomain fd,SecondDomain sd where \
          sd.firstDomain.id=fd.id and fd.name like :name and sd.email like :email \ 
          and sd.dateCreated = (select max(sd2.dateCreated) from SecondDomain sd2 \ 
                where sd2.firstDomain.id = fd.id))",
    [email:'%gmail%',name:'M%'], [max: 10, offset: 0]) 
    

    sample code : 只需点击 firstDomainController

            def fd
            // most recent email is gmail
            fd = new FirstDomain(name:"Mtest")
            fd.addToSecondDomain(new SecondDomain(email:'yahoo.com'))
            fd.addToSecondDomain(new SecondDomain(email:'gmail.com'))
            fd.save(flush:true)
    
            // most recent is yahoo
            fd = new FirstDomain(name:"MMtest")
            fd.addToSecondDomain(new SecondDomain(email:'gmail.com'))
            fd.addToSecondDomain(new SecondDomain(email:'yahoo.com'))
            fd.save(flush:true)
    
            // will return "Mtest"
            FirstDomain.executeQuery("select fd from FirstDomain fd,SecondDomain sd where sd.firstDomain.id=fd.id and fd.name like :name and sd.email like :email and sd.dateCreated = (select max(sd2.dateCreated) from SecondDomain sd2 where sd2.firstDomain.id = fd.id))",[email:'%gmail%',name:'M%'])
    

    【讨论】:

    • 这个查询每次都给我一个空列表。
    • 你有满足要求的数据吗?查询区分大小写。我几乎使用了您的域并构建了一些示例数据并对其进行了测试。今晚我会把代码签到github。
    • 我创建了名为 Manish 的 DomainA 实例和带有电子邮件 test@gmail.com 的 DomainB 实例,查询给了我空列表。等待仓库。谢谢
    • 您的查询总是可以正常工作,我尝试使用offset: 5 并且没有在数据库中提供足够的数据是我的错。非常感谢您的时间和精力。
    【解决方案2】:

    在 Grails 2.4 中,您应该能够使用新的相关子查询功能执行以下操作:

    DomainA.where {
        name like 'M%' && exists DomainB.where { 
            id == max(id).of { email like '%gmail%' }
        }
    }
    

    很遗憾,我无法在 2.4 中测试我们的应用程序,所以我无法确认这是否可行。

    【讨论】:

    • 我正在使用 grails 2.3.5,您的查询给了我错误,我已使用 grails.org/doc/2.3.7/guide/GORM.html#whereQueries 文档更正了此问题。您的查询给了我不正确的结果。它包括最近的 DomainB 不是 gmail 但在旧记录中有 gamil 的 DomainA 实例。
    猜你喜欢
    • 1970-01-01
    • 2021-04-10
    • 2016-07-29
    • 1970-01-01
    • 1970-01-01
    • 2012-06-22
    • 1970-01-01
    • 1970-01-01
    • 2021-02-17
    相关资源
    最近更新 更多