0

我想根据几个过滤器查询属性并动态构建条件

Domain Class
PatientAttr {
   def name
   def value
}

标准建筑规范

    if(filters.size() != 0 ){
        def criteria =  PatientAttr.createCriteria()
        def results = criteria.list{
            for (item in filters){
                def name = item.name
                def filter = item.filter
                and{
                    eq 'name', name
                    if(filter[0] == "lt")
                        lt ('value', filter[1] as Double)
                    else if(filter[0] == "gt")
                        gt ('value', filter[1] as Double)
                    else 
                        between ('value', filter[0] as Double, filter[1] as Double)
                }
            }
        } 

我发现只有列表的最后一个“and”语句正在被评估。标准构建器是否允许您动态构建标准?

上面的代码应该等价于这个

        def results = criteria.list{
            and{
                eq 'name', "Serum albumin (g/dL)"
                gt 'value', 3.5 as Float
            }
            and{    
                eq 'name', "M-spike (g/dL)"
                gt 'value', 2.3 as Float
            }
        }
4

2 回答 2

1

我不知道您为什么会遇到麻烦,但是由于查询的默认连接是and,因此根本没有理由在您的示例中使用and{}闭包。您上面的查询与以下内容相同:

    def results = criteria.list{
        eq 'name', "Serum albumin (g/dL)"
        gt 'value', 3.5 as Float
        eq 'name', "M-spike (g/dL)"
        gt 'value', 2.3 as Float
    }

如果您希望将顶层项目or放在一起,则需要将外部块包装在or{}闭包中:

if(filters.size() != 0 ){
    def criteria =  PatientAttr.createCriteria()
    def results = criteria.list{
        or{
            for (item in filters){
                def name = item.name
                def filter = item.filter
                and{
                    eq 'name', name
                    if(filter[0] == "lt")
                        lt ('value', filter[1] as Double)
                    else if(filter[0] == "gt")
                        gt ('value', filter[1] as Double)
                    else 
                        between ('value', filter[0] as Double, filter[1] as Double)
                }
            }
        }
    } 

这将返回一个查询,其结果如下:

名称为“血清白蛋白...”且值大于“3.5”

名称为“M-spike...”且值大于 2.3
或等

希望这会有所帮助。

于 2012-04-11T20:58:53.227 回答
0

在你的街区:

    def results = criteria.list{
        and{
            eq 'name', "Serum albumin (g/dL)"
            gt 'value', 3.5 as Float
        }
        and{    
            eq 'name', "M-spike (g/dL)"
            gt 'value', 2.3 as Float
        }
    }

你的意思是表达:

((name == "Serum albumin (g/dL)") or (value == 3.5))
and
((name == "M-spike (g/dL)") or (value == 3.3))

那么你的代码应该是:

if(filters.size() != 0 ){
    def criteria =  PatientAttr.createCriteria()
    def results = criteria.list{
        and{
            for (item in filters){
                def name = item.name
                def filter = item.filter
                or {
                    eq 'name', name
                    if(filter[0] == "lt")
                        lt ('value', filter[1] as Double)
                    else if(filter[0] == "gt")
                        gt ('value', filter[1] as Double)
                    else 
                        between ('value', filter[0] as Double, filter[1] as Double)
                }
            }
        }
    } 

如果你想表达:

((name == "Serum albumin (g/dL)") and (value == 3.5))
and
((name == "M-spike (g/dL)") and (value == 3.3))

那么你的代码应该是:

if(filters.size() != 0 ){
    def criteria =  PatientAttr.createCriteria()
    def results = criteria.list{
        and{
            for (item in filters){
                def name = item.name
                def filter = item.filter
                eq 'name', name
                if(filter[0] == "lt")
                    lt ('value', filter[1] as Double)
                else if(filter[0] == "gt")
                    gt ('value', filter[1] as Double)
                else 
                    between ('value', filter[0] as Double, filter[1] as Double)
            }
        }
    } 

因为 and 是默认操作,所以可以省略 and 方法。

于 2012-04-11T22:21:14.987 回答