文章
Michael Lei · 六月 7 阅读大约需 3 分钟

InterSystems 最佳实践之--发挥 $Query 的最大作用

我今天遇到了一个有趣的ObjectScript用例,有一个通用的解决方案,我想与大家分享。

用例:

我有一个JSON数组(在本例中具体而言是一个来自Jira的问题数组),我想在几个字段上进行聚合--例如,类别、优先级和问题类型。然后,我想把聚合的数据编平化到一个简单的列表中,其中包含每个组的总数。当然,对于聚合来说,使用一个本地数组的形式是有意义的,即:

agg(category, priority, type) = total

这样,对于输入数组中的每一条记录,我可以只用:

Do $increment(agg(category, priority, type))

但是一旦我做了聚合,我想把它变成一种更容易迭代的形式,比如一个整数下标的数组:

summary = n
summary(1) = $listbuild(total1, category1, priority1, type1)
...
summary(n) = $listbuild(totalN, categoryN, priorityN, typeN)

基础解决方案:

简单的方法是,用$Order嵌套三个For循环--比如说:

Set category = ""
For {
    Set category = $Order(agg(category))
    Quit:category=""
    
    Set priority = ""
    For {
        Set priority = $Order(agg(category,priority))
        Quit:priority=""
        
        Set type = ""
        For {
            Set type = $Order(agg(category,priority,type),1,total)
            Quit:type=""
            
            Set summary($i(summary)) = $listbuild(total,category,priority,type)
        }
    }

}

这就是我开始使用的方法,但它有很多代码,而且如果我有更多的维度来聚合,它很快就会变得不方便了。这让我想知道--是否有一个通用的解决方案来完成同样的事情?事实证明是有的!

使用 $Query的优化方案:

我决定使用$query会有帮助。请注意,这个解决方案假定整个本地数组中子标/值的深度是一致的;如果没有了这个假设,就会导致奇怪的结果.

ClassMethod Flatten(ByRef deep, Output flat) [ PublicList = deep ]
{
    Set reference = "deep"
    For {
        Set reference = $query(@reference)
        Quit:reference=""
        Set value = $listbuild(@reference)
        For i=1:1:$qlength(reference) {
            Set value = value_$listbuild($qsubscript(reference,i))
        }
        Set flat($i(flat)) = value
    }
}

所以以上片段被替换为:

Do ..Flatten(.agg,.summary)

几点需要注意的:

  • deep 需要在PublicList中,以便$query能够对其进行操作
  • 在每个迭代中,reference 被改变为引用deep中下一组有价值的子标号--例如,值可能是:deep("foo", "bar")
  • $qlength 返回reference中子标的数量
  • $qsubscript 返回reference中第i个下标的值
  • 当$listbuild列表被串联起来时,一个有效的$listbuild列表与合并后的列表就得出结果(这比使用任何其他分隔符都要好!)

总结

$query, $qlength, 和 $qsubscript 在处理任意深度的Global/Local数组时非常方便。

进阶阅读

$Query: https://docs.intersystems.com/irisforhealthlatest/csp/docbook/DocBook.UI...
$QSubscript: https://docs.intersystems.com/irisforhealthlatest/csp/docbook/Doc.View.c...
$QLength: https://docs.intersystems.com/irisforhealthlatest/csp/docbook/Doc.View.c...

0
0 28
讨论 (0)1
登录或注册以继续