Artigo
· Mar. 18, 2021 3min de leitura

Aproveitando ao máximo $ Query

Encontrei um caso de uso interessante do ObjectScript hoje com uma solução geral que gostaria de compartilhar.

Caso de uso:  

Eu tenho uma matriz JSON (especificamente, no meu caso, uma matriz de problemas de Jira) que desejo agregar em alguns campos - digamos, categoria, prioridade e tipo de problema. Em seguida, desejo nivelar os agregados em uma lista simples com o total de cada um dos grupos. Claro, para a agregação, faz sentido usar uma matriz local na forma:

agg(category, priority, type) = total

De modo que, para cada registro na matriz de entrada, posso apenas:

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

Mas depois de fazer a agregação, quero colocá-la em uma forma mais fácil de iterar, como uma matriz subscrita por inteiro:

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

Solução Básica:

A abordagem simples é ter três loops For aninhados com $ Order - por exemplo:

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)
        }
    }

Foi com isso que comecei, mas é muito código, e se eu tivesse mais dimensões para agregar sobre ele ficaria complicado rapidamente. Isso me fez pensar - existe uma solução geral para realizar a mesma coisa? Acontece que existe!

Melhor solução com $ Query:

Decidi que usar $ query ajudaria. Observe que esta solução assume uma profundidade uniforme de subscritos / valores em todo o array local; coisas estranhas aconteceriam se essa suposição fosse violada.  

 

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
    }
}

Portanto, o snippet acima é substituído por:

Do ..Flatten(.agg,.summary)

Algumas coisas a serem observadas sobre esta solução:

deep precisa estar na PublicList para que $ query possa operar nela em cada iteração, a referência é alterada para fazer referência ao próximo conjunto de subscritos em profundidade que tem um valor - por exemplo, o valor pode ser: deep ("foo", "bar") $ qlength retorna o número de subscritos em referência $ qsubscript retorna o valor do i'ésimo subscrito de referência Quando as listas $ listbuild são concatenadas, o resultado é uma lista $ listbuild válida com as listas combinadas (isso é muito melhor do que usar qualquer outro delimitador!) Resumo $ query, $ qlength e $ qsubscript são úteis para lidar com matrizes globais / locais de profundidade arbitrária.

Leitura Adicional

$Query: https://docs.intersystems.com/irisforhealthlatest/csp/docbook/DocBook.UI.Page.cls?KEY=RCOS_FQUERY

$QSubscript: https: //docs.intersystems.com/irisforhealthlatest/csp/docbook/Doc.View.c ... 

$QLength: https: //docs.intersystems.com/irisforhealthlatest/csp/docbook/Doc.View.c ...

Discussão (0)0
Entre ou crie uma conta para continuar