Esta seção descreve:
as funções e operadores para processar e criar dados JSON
a linguagem de caminho SQL/JSON
as funções de consulta SQL/JSON
Para fornecer suporte nativo a tipos de dados JSON no ambiente SQL, PostgreSQL implementa o modelo de dados SQL/JSON. Este modelo compreende sequências de itens. Cada item pode conter valores escalares SQL, com um valor nulo SQL/JSON adicional, e estruturas de dados compostas que utilizam matrizes e objetos JSON. O modelo é uma formalização do modelo de dados implícito na especificação JSON RFC 7159.
O SQL/JSON permite tratar dados JSON juntamente com dados SQL regulares, com suporte a transações, incluindo:
Carregar dados JSON no banco de dados e armazená-los em colunas SQL regulares como cadeias de caracteres ou binárias.
Geração de objetos e matrizes JSON a partir de dados relacionais.
Consultar dados JSON usando funções de consulta SQL/JSON e expressões de linguagem de caminho SQL/JSON.
Para aprender mais sobre o padrão SQL/JSON, veja [sqltr-19075-6] (ISO/IEC 19075-6:2021). Para obter detalhes sobre os tipos de dados JSON com suporte pelo PostgreSQL, veja a Seção 8.14.
A Tabela 9.47 descreve os operadores
disponíveis para uso com tipos de dados JSON
(veja a Seção 8.14).
Além disso, os operadores de comparação usuais descritos na
Tabela 9.1 estão disponíveis
para o tipo de dados jsonb, embora não para o
tipo de dados json.
Os operadores de comparação seguem as regras de ordenação para
operações de árvore-B descritas na
Seção 8.14.4.
Veja também na Seção 9.21 a função
de agregação json_agg, que agrega valores de
registro como JSON, a função de agregação
json_object_agg, que agrega pares de valores em
um objeto JSON, e suas equivalentes para o
tipo de dados jsonb jsonb_agg e
jsonb_object_agg.
Tabela 9.47. Operadores dos tipos de dados json e jsonb
Operador Descrição Exemplo(s) |
|---|
Extrai o
|
Extrai o campo do objeto JSON com a chave fornecida.
|
Extrai o
|
Extrai o campo do objeto JSON com a chave
fornecida, como o tipo de dados
|
Extrai o subobjeto JSON no caminho especificado, onde os elementos do caminho podem ser chaves de campo ou índices de matriz.
|
Extrai o subobjeto JSON no caminho
especificado, como o tipo de dados
|
Os operadores de extração de campo/elemento/caminho retornam
NULL, em vez de erro, se a entrada
JSON não tiver a estrutura correta para
corresponder à solicitação;
por exemplo, se não existir tal chave ou elemento de matriz.
Alguns outros operadores existem apenas para o tipo de dados
jsonb, conforme descrito na
Tabela 9.48.
A Seção 8.14.4 descreve como estes operadores
podem ser usados para procurar dados do tipo de dados
jsonb indexados.
Tabela 9.48. Operadores adicionais para o tipo de dados jsonb
Operador Descrição Exemplo(s) |
|---|
O primeiro valor JSON contém o segundo? (Veja a Seção 8.14.3 para obter detalhes sobre contém/está contido.)
|
O primeiro valor JSON está contido no segundo?
|
A cadeia de caracteres de texto existe como uma chave de nível superior, ou elemento de matriz, no valor JSON?
|
Alguma das cadeias de caracteres da matriz de texto existe como chave de nível superior ou como elemento da matriz?
|
Todas as cadeias de caracteres da matriz de texto existem como chaves de nível superior ou como elementos da matriz?
|
Concatena dois valores do tipo de dados
Para anexar uma matriz a outra matriz como uma única entrada, envolva-a em uma camada adicional de matriz, por exemplo:
|
Exclui uma chave (e seu valor) de um objeto JSON, ou valores cadeia de caracteres que correspondem de uma matriz JSON.
|
Exclui do operando esquerdo todas as chaves ou elementos de matriz que correspondem.
|
Exclui o elemento da matriz com o índice especificado (inteiros negativos contam a partir do final). Gera um erro se o valor JSON não for uma matriz.
|
Exclui o campo, ou elemento de matriz, no caminho especificado, onde os elementos de caminho podem ser chaves de campo ou índices de matriz.
|
O caminho JSON retorna algum item para o valor JSON especificado? (É útil apenas com expressões de caminho JSON padrão SQL, mas não para expressões de verificação de predicado, já que estas sempre retornam um valor.)
|
Retorna o resultado de uma verificação de predicado de caminho
JSON para o valor JSON especificado.
(É útil apenas para
expressões
de verificação de predicado, mas não para expressões de
caminho JSON padrão SQL,
porque retornará
|
Os operadores jsonpath @? e
@@ suprimem os seguintes erros: campo de objeto
ou elemento de matriz ausente, tipo de item JSON
inesperado, erros de data e hora e erros numéricos.
As funções relacionadas a jsonpath descritas abaixo
também podem ser configuradas para suprimir estes tipos de erros.
Este comportamento pode ser útil ao pesquisar coleções de documentos
JSON com estruturas variadas.
A Tabela 9.49 descreve as funções
disponíveis para construção de valores dos tipos de dados
json e jsonb.
Algumas funções nesta tabela possuem a cláusula
RETURNING, que especifica o tipo de dados a ser
retornado.
Deve ser escolhido um entre json, jsonb,
bytea, uma cadeia de caracteres do tipo de dados
(text, char ou varchar),
ou um tipo de dados que pode ser convertido para json.
Por padrão, o tipo de dados retornado é json.
Tabela 9.49. Funções de criação de tipos de dados JSON
Função Descrição Exemplo(s) |
|---|
|
Converte qualquer valor SQL para os
tipos de dados
|
Converte uma matriz SQL em uma matriz
JSON.
O comportamento é o mesmo da função
|
Constrói uma matriz JSON a partir de uma
série de parâmetros
|
Converte um valor composto SQL em um objeto
JSON.
O comportamento é o mesmo da função
|
Cria uma matriz JSON, com tipos de dados
potencialmente heterogêneos, a partir de uma lista de
argumentos de comprimento variável.
Cada argumento é convertido segundo
|
Cria um objeto JSON a partir de uma lista de
argumentos de comprimento variável.
Por convenção, a lista de argumentos consiste em chaves e
valores alternados.
Os argumentos chave são convertidos em texto;
os argumentos valor são convertidos pelas funções
|
Constrói um objeto JSON com todos os pares
chave/valor fornecidos, ou um objeto vazio caso não seja
fornecido nenhum par.
|
|
Cria um objeto JSON a partir de uma matriz de texto. A matriz deve ter exatamente uma dimensão com um número par de elementos, que neste caso são considerados como pares de chave e valor alternados, ou deve ter duas dimensões, de modo que cada matriz interna tenha exatamente dois elementos, considerados como um par chave e valor. Todos os valores são convertidos em cadeias de caracteres JSON.
|
Esta forma da função
|
|
Converte a expressão fornecida, especificada como
|
|
Converte um valor escalar SQL fornecido
em um valor escalar JSON.
Se a entrada for
|
|
Converte uma expressão SQL/JSON
em uma cadeia de caracteres ou binária.
A
|
A Tabela 9.50 detalha as possibilidades SQL/JSON para testar JSON.
Tabela 9.50. Funções de teste de SQL/JSON
A Tabela 9.51 descreve as
funções disponíveis para processar valores dos tipos de dados
json e jsonb.
Tabela 9.51. Funções de processamento de tipos de dados JSON
Função Descrição Exemplo(s) |
|---|
Expande a matriz JSON de nível superior em um conjunto de valores JSON.
value ----------- 1 true [2,false]
|
Expande a matriz JSON de nível superior
em um conjunto de valores do tipo de dados
value ----------- foo bar
|
Retorna o número de elementos na matriz JSON de nível superior.
|
Expande o objeto JSON de nível superior em um conjunto de pares de chave/valor.
key | value -----+------- a | "foo" b | "bar"
|
Expande o objeto JSON de nível superior
em um conjunto de pares de chave/valor.
O
key | value -----+------- a | foo b | bar
|
Extrai o subobjeto JSON no caminho especificado.
(É funcionalmente equivalente ao operador
|
Extrai o subobjeto JSON no caminho
especificado como o tipo de dados
|
Retorna o conjunto de chaves no objeto JSON de nível superior.
json_object_keys ------------------ f1 f2
|
Expande o objeto JSON de nível superior para uma linha tendo o
tipo de dados composto do argumento Para converter um valor JSON para o tipo de dados SQL de uma coluna de saída, são aplicadas as seguintes regras em sequência:
Embora o exemplo abaixo use uma constante para o valor JSON,
o uso típico seria fazer uma referência lateral a uma coluna
do tipo de dados
a | b | c
---+-----------+-------------
1 | {2,"a b"} | (4,"a b c")
|
Função para testar
jsonb_populate_record_valid ----------------------------- f (1 linha)
ERROR: value too long for type character(2)
jsonb_populate_record_valid ----------------------------- t (1 linha)
a ---- aa (1 linha)
|
Expande a matriz de objetos JSON de nível superior para um
conjunto de linhas com o tipo de dados composto do argumento
a | b ---+--- 1 | 2 3 | 4
|
Expande o objeto JSON de nível superior para
uma linha com o tipo de dados composto definido por uma cláusula
a | b | c | d | r
---+---------+---------+---+---------------
1 | [1,2,3] | {1,2,3} | | (123,"a b c")
|
Expande a matriz de objetos JSON de nível superior para um
conjunto de linhas com o tipo de dados composto definido por
uma cláusula
a | b ---+----- 1 | foo 2 | (2 linhas)
|
Retorna o
|
Se
|
Retorna
|
Remove todos os campos do objeto com valor nulo do valor
JSON fornecido, recursivamente.
Se
|
Verifica se o caminho JSON retorna algum item para o valor
JSON especificado.
(É útil apenas com expressões de caminho JSON
padrão SQL, mas não para
expressões
de verificação de predicado, já que estas sempre retornam
um valor.)
Se for especificado o argumento
|
Retorna o resultado booleano SQL de uma
verificação de predicado de caminho JSON
para o valor JSON especificado.
(É útil apenas para
expressões
de verificação de predicado, mas não para expressões de
caminho JSON padrão SQL,
uma vez que irá falhar ou retornar
|
Retorna todos os itens JSON retornados pelo caminho JSON para
o valor JSON especificado.
Para expressões de caminho JSON padrão
SQL, retorna os valores JSON
selecionados de
jsonb_path_query ------------------ 2 3 4
|
Retorna todos os itens JSON retornados pelo
caminho JSON para o valor JSON
especificado, como uma matriz JSON.
Os parâmetros são os mesmos que para a função
|
Retorna o primeiro item JSON retornado pelo
caminho JSON para o valor JSON
especificado, ou
|
Estas funções agem como suas contrapartes descritas acima sem o
sufixo
|
|
Converte o valor JSON fornecido em texto
indentado e com impressão estruturada
(
[
{
"f1": 1,
"f2": null
},
2
]
|
|
Retorna o tipo de dados do valor JSON
de nível superior como uma cadeia de caracteres de texto.
Os tipos de dados possíveis são:
|
As expressões de caminho SQL/JSON
indicam os itens a serem recuperados de um valor JSON,
de forma semelhante às expressões XPath usadas para acessar
conteúdo XML.
No PostgreSQL, as expressões de caminho
são implementadas como o tipo de dados jsonpath, podendo
usar quaisquer elementos descritos na
Seção 8.14.7.
As funções e operadores de consulta JSON passam
a expressão de caminho fornecida para o
mecanismo de caminho para avaliação.
Se a expressão corresponder aos dados JSON
consultados, o item JSON correspondente,
ou conjunto de itens, será retornado.
Se não houver correspondência, o resultado será
NULL, false ou um erro,
dependendo da função.
As expressões de caminho são escritas na linguagem de caminho
SQL/JSON, podendo incluir
expressões e funções aritméticas.
Uma expressão de caminho consiste em uma sequência de elementos
permitidos pelo tipo de dados jsonpath.
A expressão de caminho é normalmente avaliada da esquerda para a
direita, mas podem ser usados parênteses para alterar a ordem das
operações.
Se a avaliação for bem-sucedida, será produzida uma sequência de itens
JSON e o resultado da avaliação será retornado para
a função de consulta JSON que conclui a computação
especificada.
Para se referir ao valor JSON que está sendo consultado
(o item de contexto), deve ser usada a variável
$ na expressão do caminho.
O primeiro elemento de um caminho deve ser sempre o $.
Este pode ser seguido por um ou mais
operadores de acesso
que percorrem a estrutura JSON nível por nível
para recuperar subitens do item de contexto.
Cada operador de acesso atua sobre o(s) resultado(s) da etapa de
avaliação anterior, produzindo zero, um ou mais itens de saída a
partir de cada item de entrada.
Por exemplo, suponha que temos alguns dados JSON de um rastreador GPS que gostaríamos de analisar, tal como:
SELECT '{
"track": {
"segments": [
{
"location": [ 47.763, 13.4034 ],
"start time": "2018-10-14 10:05:14",
"HR": 73
},
{
"location": [ 47.706, 13.2635 ],
"start time": "2018-10-14 10:39:21",
"HR": 135
}
]
}
}' AS json \gset
(O exemplo acima pode ser copiado e colado no
psql para configurar os exemplos a seguir.
Então o psql irá expandir o
:'json' em uma constante de cadeia de caracteres
devidamente entre aspas contendo o valor JSON.)
Para recuperar os segmentos de trilha disponíveis, é necessário usar
o operador de acesso
.
para detalhar os objetos JSON ao redor:
key
=>SELECT jsonb_path_query(:'json', '$.track.segments');
jsonb_path_query
-----------------------------------------------------------------------------------
[{"HR": 73, "location": [47.763, 13.4034], "start time": "2018-10-14 10:05:14"}, ↵
{"HR": 135, "location": [47.706, 13.2635], "start time": "2018-10-14 10:39:21"}]
(1 linha)
Para recuperar o conteúdo de uma matriz, normalmente é usado o
operador [*].
O exemplo a seguir retornar as coordenadas de localização para
todos os segmentos de trilha disponíveis:
=>SELECT jsonb_path_query(:'json', '$.track.segments[*].location');
jsonb_path_query ------------------- [47.763, 13.4034] [47.706, 13.2635] (2 linhas)
Aqui começamos com todo o valor de entrada JSON
($), então o acessador .track
selecionou o objeto JSON associado à chave de
objeto "track", então o acessador
.segments selecionou a matriz JSON
associada à chave "segments" dentro deste objeto,
então o acessador [*] selecionou cada elemento
desta matriz (produzindo uma série de itens),
então o acessador .location selecionou a matriz
JSON associada à chave "location"
dentro de cada um destes objetos.
Neste exemplo, cada um destes objetos tinha uma chave
"location"; mas se algum deles não tivesse,
o acessador .location simplesmente não produziria
nenhuma saída para este item de entrada.
Para retornar apenas as coordenadas do primeiro segmento, pode ser
especificado o índice correspondente no operador de acesso
[].
Lembre-se de que os índices de matrizes JSON
são relativos a partir de zero:
=>SELECT jsonb_path_query(:'json', '$.track.segments[0].location');
jsonb_path_query ------------------- [47.763, 13.4034] (1 linha)
O resultado de cada etapa de avaliação de caminho pode ser processado
por um ou mais dos operadores e métodos jsonpath listados
na Seção 9.16.2.3.
Cada nome de método deve ser precedido por um ponto.
Por exemplo, pode ser obtido o tamanho de uma matriz:
=>SELECT jsonb_path_query(:'json', '$.track.segments.size()');
jsonb_path_query ------------------ 2 (1 linha)
Mais exemplos de uso dos operadores e métodos para o tipo de dados
jsonpath em expressões de caminho aparecem abaixo na
Seção 9.16.2.3.
Um caminho também pode conter expressões de filtro que funcionam de forma semelhante à cláusula WHERE do SQL. Uma expressão de filtro começa com um ponto de interrogação e fornece uma condição entre parênteses:
? (condição)
As expressões de filtro devem ser escritas logo após a etapa de
avaliação do caminho à qual se aplicam.
O resultado desta etapa é filtrado para incluir apenas os itens
que satisfazem a condição fornecida.
SQL/JSON define lógica de três
valores, portanto a condição pode produzir
true, false,
ou unknown.
O valor unknown desempenha o mesmo papel que o
NULL no SQL, podendo ser
testado com o predicado is unknown.
As etapas subsequentes de avaliação de caminho utilizam apenas os
itens para os quais a expressão de filtro retornou
true.
As funções e operadores que podem ser usados em expressões de filtro
estão listados na Tabela 9.53.
Dentro de uma expressão de filtro, a variável @
denota o valor que está sendo considerado
(ou seja, um resultado da etapa de caminho anterior).
Podem ser escritos operadores de acesso após o @
para recuperar os itens de componentes.
Por exemplo, suponha que se queira recuperar todos os valores de frequência cardíaca superiores a 130. Isto pode ser conseguido da seguinte maneira:
=>SELECT jsonb_path_query(:'json', '$.track.segments[*].HR ? (@ > 130)');
jsonb_path_query ------------------ 135 (1 linha)
Para obter as horas de início dos segmentos com estes valores, é necessário filtrar os segmentos irrelevantes antes de selecionar as horas de início. Portanto, a expressão de filtro é aplicada à etapa anterior e o caminho usado na condição é diferente:
=>SELECT jsonb_path_query(:'json', '$.track.segments[*] ? (@.HR > 130)."start time"');
jsonb_path_query ----------------------- "2018-10-14 10:39:21" (1 linha)
Podem ser usadas várias expressões de filtro em sequência, se for necessário. O exemplo a seguir seleciona as horas de início de todos os segmentos que contêm locais com coordenadas relevantes e valores elevados de frequência cardíaca:
=>SELECT jsonb_path_query(:'json', '$.track.segments[*] ? (@.location[1] < 13.4) ? (@.HR > 130)."start time"');
jsonb_path_query ----------------------- "2018-10-14 10:39:21" (1 linha)
Também é permitido usar expressões de filtro em níveis diferentes de aninhamento. O exemplo a seguir primeiro filtra todos os segmentos por localização e, em seguida, retorna valores elevados de frequência cardíaca para estes segmentos, se disponíveis:
=>SELECT jsonb_path_query(:'json', '$.track.segments[*] ? (@.location[1] < 13.4).HR ? (@ > 130)');
jsonb_path_query ------------------ 135 (1 linha)
Também podem ser aninhadas expressões de filtro umas dentro das outras. Este exemplo retorna o tamanho da trilha se ela contiver algum segmento com valores altos de frequência cardíaca, ou uma sequência vazia caso contrário:
=>SELECT jsonb_path_query(:'json', '$.track ? (exists(@.segments[*] ? (@.HR > 130))).segments.size()');
jsonb_path_query ------------------ 2 (1 linha)
A implementação da linguagem de caminho SQL/JSON no PostgreSQL apresenta os seguintes desvios em relação ao padrão SQL/JSON.
Como uma extensão do padrão SQL, uma expressão
de caminho do PostgreSQL pode ser um
predicado booleano, enquanto o padrão SQL
permite predicados apenas dentro de filtros.
Enquanto as expressões de caminho padrão SQL
retornam o(s) elemento(s) relevante(s) do valor JSON
consultado, as expressões de verificação de predicado retornam um
resultado do tipo de dados jsonb com três valores
possíveis para a verificação de predicado: true,
false ou null.
Por exemplo, poderia ser escrita esta expressão de filtro padrão
SQL:
=>SELECT jsonb_path_query(:'json', '$.track.segments ?(@[*].HR > 130)');
jsonb_path_query
---------------------------------------------------------------------------------
{"HR": 135, "location": [47.706, 13.2635], "start time": "2018-10-14 10:39:21"}
(1 linha)
A expressão semelhante de verificação de predicado simplesmente
retorna true indicando que existe uma
correspondência:
=>SELECT jsonb_path_query(:'json', '$.track.segments[*].HR > 130');
jsonb_path_query ------------------ true (1 linha)
Exemplo 9.3. Exemplo do tradutor
Tipo de dados retornado pela consulta acima:
SELECT pg_typeof(jsonb_path_query(:'json', '$.track.segments[*].HR > 130'));
pg_typeof ----------- jsonb (1 linha)
As expressões de verificação de predicados são requerida no
operador @@ (e na função
jsonb_path_match), e não devem ser usadas
com o operador @?
(ou com a função jsonb_path_exists).
Existem pequenas diferenças na interpretação dos padrões de
expressão regular usadas nos filtros like_regex.
conforme descrito na Seção 9.16.2.4.
Ao consultar dados JSON, a expressão do caminho pode não corresponder à estrutura real dos dados JSON. Uma tentativa de acessar um membro inexistente de um objeto ou um elemento de uma matriz é definida como um erro estrutural. As expressões de caminho SQL/JSON possuem dois modos de lidar com erros estruturais:
lax (Flexível) (o padrão) — O mecanismo de caminho adapta implicitamente os dados consultados ao caminho especificado. Quaisquer erros estruturais que não possam ser corrigidos conforme descrito abaixo são suprimidos, não produzindo nenhuma correspondência.
strict (Estrito) — Se ocorrer um erro estrutural, será gerado um erro.
O modo flexível facilita a correspondência entre um documento JSON e uma expressão de caminho quando os dados JSON não estão em conformidade com o esquema esperado. Se um operando não corresponder aos requisitos de uma determinada operação, ele poderá ser automaticamente encapsulado como uma matriz SQL/JSON ou desencapsulado convertendo seus elementos em uma sequência SQL/JSON antes de executar a operação. Além disso, os operadores de comparação desempacotam automaticamente seus operandos no modo flexível, permitindo comparar matrizes SQL/JSON sem necessidade de configurações adicionais. Uma matriz de tamanho 1 é considerada igual ao seu único elemento. O desempacotamento automático não é realizado quando:
A expressão de caminho contém os métodos type()
ou size() que retornam o tipo de dados e o
número de elementos na matriz, respectivamente.
Os dados JSON consultados contêm matrizes aninhadas. Neste caso, apenas a matriz mais externa é desempacotada, enquanto todos as matrizes internas permanecem inalteradas. Assim, o desempacotamento implícito só pode ocorrer um nível abaixo em cada etapa de avaliação do caminho.
Por exemplo, ao consultar os dados de GPS listados acima, se pode abstrair o fato de que ele armazena uma matriz de segmentos ao usar o modo flexível:
=>SELECT jsonb_path_query(:'json', 'lax $.track.segments.location');
jsonb_path_query ------------------- [47.763, 13.4034] [47.706, 13.2635] (2 linhas)
No modo estrito, o caminho especificado deve corresponder exatamente à estrutura do documento JSON consultado; portanto, usar esta expressão de caminho causará um erro:
=>SELECT jsonb_path_query(:'json', 'strict $.track.segments.location');ERRO: acessador de membro jsonpath só pode ser aplicado a um objeto
Para obter o mesmo resultado que no modo flexível, é necessário
desempacotar explicitamente a matriz segments:
=>SELECT jsonb_path_query(:'json', 'strict $.track.segments[*].location');
jsonb_path_query ------------------- [47.763, 13.4034] [47.706, 13.2635] (2 linhas)
O comportamento de desempacotamento do modo flexível pode levar
a resultados surpreendentes.
Por exemplo, a seguinte consulta usando o acessador .**
seleciona cada valor HR duas vezes:
=>SELECT jsonb_path_query(:'json', 'lax $.**.HR');
jsonb_path_query ------------------ 73 135 73 135 (4 linhas)
Isto acontece porque o acessador `.**` seleciona
tanto a matriz `segments` quanto cada um de seus
elementos, enquanto o acessador .HR desempacota
automaticamente matrizes ao usar o modo flexível.
Para evitar resultados inesperados, se recomenda usar o acessador
.** somente no modo estrito.
A consulta a seguir seleciona cada valor de HR
apenas uma vez:
=>SELECT jsonb_path_query(:'json', 'strict $.**.HR');
jsonb_path_query ------------------ 73 135 (2 linhas)
O desempacotamento de matrizes também pode levar a resultados inesperados.
Considere este exemplo, que seleciona todas as matrizes de
location:
=>SELECT jsonb_path_query(:'json', 'lax $.track.segments[*].location');
jsonb_path_query ------------------- [47.763, 13.4034] [47.706, 13.2635] (2 linhas)
Como esperado, retorna as matrizes completas. Mas aplicar uma expressão de filtro faz com que as matrizes sejam desempacotadas para avaliar cada item, retornando apenas os itens que correspondem à expressão:
=>SELECT jsonb_path_query(:'json', 'lax $.track.segments[*].location ?(@[*] > 15)');
jsonb_path_query ------------------ 47.763 47.706 (2 linhas)
Isto ocorre apesar das matrizes completas serem selecionados pela expressão do caminho. Use o modo estrito para restaurar a seleção das matrizes:
=>SELECT jsonb_path_query(:'json', 'strict $.track.segments[*].location ?(@[*] > 15)');
jsonb_path_query ------------------- [47.763, 13.4034] [47.706, 13.2635] (2 linhas)
A Tabela 9.52 descreve os operadores
e métodos disponíveis para o tipo de dados jsonpath.
Note que, embora os operadores e métodos unários possam ser aplicados
a múltiplos valores resultantes de uma etapa de caminho anterior,
Os operadores binários (adição, etc.) só podem ser aplicados a
valores individuais.
No modo flexível, os métodos aplicados a uma matriz serão executados
para cada valor na matriz.
As exceções são .type() e .size(),
que são aplicados à própria matriz.
Tabela 9.52. Operadores e métodos para o tipo de dados jsonpath
Operador/Método Descrição Exemplo(s) |
|---|
Adição
|
Mais unário (sem operação); ao contrário da adição, pode iterar sobre vários valores
|
Subtração
|
Negação; ao contrário da subtração, pode iterar sobre vários valores
|
Multiplicação
|
Divisão
|
Módulo (resto)
|
Tipo de dados do item JSON
(veja a função
|
Tamanho do item JSON (número de elementos da matriz, ou 1 se não for uma matriz)
|
Valor booleano convertido a partir de um valor booleano, número ou cadeia de caracteres em JSON.
|
Valor cadeia de caracteres convertido a partir de um JSON booleano, numérico, cadeia de caracteres ou data/hora.
|
Número de ponto flutuante aproximado convertido a partir de um número ou cadeia de caracteres JSON.
|
Número inteiro mais próximo maior ou igual ao número fornecido.
|
Número inteiro mais próximo menor ou igual ao número fornecido.
|
Valor absoluto do número fornecido
|
Valor inteiro grande convertido a partir de um número ou cadeia de caracteres JSON
|
Valor decimal arredondado convertido a partir de um número
ou cadeia de caracteres JSON.
(
|
Valor inteiro convertido a partir de um número ou cadeia de caracteres JSON
|
Valor numérico convertido a partir de um número ou cadeia de caracteres JSON
|
Valor de data e hora convertido a partir de uma cadeia de caracteres
|
Valor de data e hora convertido a partir de uma cadeia de caracteres
usando o modelo de
|
Valor de data convertido a partir de uma cadeia de caracteres
|
Valor da hora sem zona horária convertido a partir de uma cadeia de caracteres
|
Valor da hora sem zona horária, convertido a partir de uma cadeia de caracteres, com frações de segundo ajustadas à precisão especificada.
|
Valor da hora com zona horária convertido a partir de uma cadeia de caracteres
|
Valor da hora com zona horária, convertido a partir de uma cadeia de caracteres, com frações de segundo ajustadas à precisão especificada.
|
Carimbo de data e hora sem valor de zona horária, convertido a partir de uma cadeia de caracteres
|
Carimbo de data e hora sem valor de zona horária, convertido a partir de uma cadeia de caracteres com frações de segundo ajustadas à precisão especificada
|
Carimbo de data e hora com valor de zona horária, convertido a partir de uma cadeia de caracteres
|
Carimbo de data e hora com valor de zona horária, convertido a partir de uma cadeia de caracteres com frações de segundo ajustadas à precisão especificada
|
Os pares chave-valor do objeto, representados como uma matriz
de objetos contendo três campos:
|
O tipo de dados do resultado dos métodos
datetime() e
datetime(
podem ser template)date, timetz, time,
timestamptz ou timestamp.
Os dois métodos determinam o tipo de dados do resultado dinamicamente.
O método datetime() tenta sequencialmente
encontrar uma correspondência entre sua cadeia de caracteres de
entrada e os formatos ISO para date,
timetz, time, timestamptz e
timestamp.
Ele para no primeiro formato que corresponde e emite o tipo de dados
correspondente.
O método datetime(
Determina o tipo de dados de resultado de acordo com os campos
usados na cadeia de caracteres de modelo fornecida.
template)
Os métodos datetime() e
datetime(
usam as mesmas regras de análise sintática que a função
SQL template)to_timestamp usa
(veja a Seção 9.8),
Com três exceções.
Em primeiro lugar, estes métodos não permitem padrões de modelo
sem correspondência.
Em segundo lugar, apenas os seguintes separadores são permitidos
na cadeia de caracteres de modelo: o sinal de menos, ponto,
barra, vírgula, apóstrofo, ponto e vírgula, dois pontos e espaço.
Em terceiro lugar, os separadores na cadeia de caracteres do modelo
devem corresponder exatamente à cadeia de caracteres de entrada.
Caso seja necessário comparar diferentes tipos de dados de
data e hora, é aplicada uma conversão implícita.
Um valor do tipo de dados date pode ser convertido
para o tipo de dados timestamp ou timestamptz,
Um valor do tipo de dados timestamp pode ser convertido
para o tipo de dados timestamptz e
um valor do tipo de dados time pode ser convertido
para o tipo de dados timetz.
Entretanto, todas estas conversões, exceto a primeira, dependem
da configuração corrente de TimeZone ,
e, portanto, só pode ser executada em funções para o tipo de dados
jsonpath que levam em consideração a zona horária.
Da mesma forma, outros métodos relacionados a data e hora que
convertem cadeias de caracteres em tipos de dados de data e hora
também realizam esta conversão, o que pode envolver a configuração
corrente de TimeZone.
Portanto, estas conversões também só podem ser realizadas dentro
de funções para o tipo de dados jsonpath que levam
em consideração a zona horária.
A Tabela 9.53 descreve os elementos de expressão de filtro disponíveis.
Tabela 9.53. Elementos de expressão de filtro para o tipo de dados jsonpath
Predicado/Valor Descrição Exemplo(s) |
|---|
Comparação de igualdade (este e os outros operadores de comparação funcionam em todos os valores escalares JSON)
|
Comparação de não igualdade
|
Comparação menor-que
|
Comparação menor-que-ou-igual
|
Comparação maior-que
|
Comparação maior-que-ou-igual
|
Constante JSON
|
Constante JSON
|
Constante JSON
|
AND booleano
|
OR booleano
|
NOT booleano
|
Testa se a condição booleana é
|
Testa se o primeiro operando corresponde à expressão regular
fornecida pelo segundo operando, opcionalmente com as
modificações descritas pelos caracteres da cadeia de caracteres
|
Testa se o segundo operando é uma sub-cadeia de caracteres no início do primeiro operando.
|
Testa se a expressão de caminho corresponde a pelo menos um item
SQL/JSON.
Retorna
|
As expressões de caminho SQL/JSON
permitem a correspondência de texto com uma expressão regular com
o filtro like_regex.
Por exemplo, a seguinte consulta de caminho
SQL/JSON faz a
correspondência, sem distinção entre letras maiúsculas e minúsculas,
de todas as cadeias de caracteres em uma matriz que começam com
uma vogal em inglês:
$[*] ? (@ like_regex "^[aeiou]" flag "i")
A cadeia de caracteres opcional flag pode
incluir um ou mais dos caracteres: i para
correspondência que não diferencia letras maiúsculas de minúsculas,
m para permitir ^ e
$ corresponderem em novas linhas;
s para permitir . corresponder
a uma nova linha; e q para delimitar todo o padrão
(reduzindo o comportamento para uma simples correspondência de
sub-cadeia de caracteres).
O padrão SQL/JSON pega
emprestado sua definição para expressões regulares do operador
LIKE_REGEX, que por sua vez usa o padrão XQuery.
No momento o PostgreSQL não oferece
suporte ao operador LIKE_REGEX.
Portanto, o filtro like_regex é implementado
usando o mecanismo de expressão regular POSIX
descrito na Seção 9.7.3.
Isto leva a várias discrepâncias menores do comportamento
SQL/JSON padrão, que estão
catalogadas na Seção 9.7.3.8.
Note, no entanto, que as incompatibilidades de letras de
sinalizador descritas lá não se aplicam a
SQL/JSON, porque as letras
de sinalizador XQuery são traduzidas para corresponder ao que
o mecanismo POSIX espera.
Tenha em mente que o argumento contendo o padrão de
like_regex é um literal cadeia de caracteres
de caminho JSON, escrito segundo as regras
fornecidas na Seção 8.14.7.
Isto significa, em particular, que quaisquer contrabarras que se
deseja usar na expressão regular devem ser duplicadas.
Por exemplo, para corresponder aos valores cadeia de caracteres do
documento raiz que contêm apenas dígitos:
$.* ? (@ like_regex "^\\d+$")
As funções de consulta SQL/JSON
JSON_EXISTS(), JSON_QUERY() e
JSON_VALUE()
descritas na Tabela 9.54 podem ser
usadas para consultar documentos JSON.
Cada uma destas funções aplica uma expressão de caminho
path_expression (uma consulta de caminho
SQL/JSON) a um item de contexto
context_item (o documento).
Veja a Seção 9.16.2 para obter mais
detalhes sobre o que a path_expression
pode conter.
A path_expression também pode fazer
referência a variáveis, cujos valores são especificados com seus
respectivos nomes na cláusula PASSING que tem
suporte por cada função.
context_item pode ser um valor do
tipo de dados jsonb ou uma cadeia de caracteres que pode
ser convertida com sucesso para o tipo de dados jsonb.
Tabela 9.54. Funções de consulta de SQL/JSON
Assinatura da função Descrição Exemplo(s) |
|---|
Exemplos:
ERRO: O índice da matriz jsonpath está fora dos limites
|
Exemplos:
ERRO: matriz mal formada: "[1, 2]" DETALHE: Faltando "]" após as dimensões da matriz.
|
Exemplos:
|
A expressão context_item é convertida para
o tipo de dados jsonb por meio de uma conversão implícita,
caso a expressão já não seja do tipo de dados jsonb.
Note, no entanto, que quaisquer erros de análise sintática que ocorram
durante esta conversão são reportados incondicionalmente, ou seja,
não são tratados de acordo com a cláusula ON ERROR
(especificada ou implícita).
A função JSON_VALUE() irá retornar o valor
NULL do SQL se
path_expression retornar o valor
null do JSON, enquanto a função
JSON_QUERY() irá retornar o valor
null do JSON tal como se encontra.
A função JSON_TABLE é uma função
SQL/JSON que consulta dados JSON
e apresenta os resultados como uma visão relacional, que pode ser
acessada como uma tabela SQL comum.
A função JSON_TABLE pode ser usada dentro da
cláusula FROM das instruções SELECT,
UPDATE ou DELETE e como fonte
de dados em uma instrução MERGE.
Tomando dados JSON como entrada, a função
JSON_TABLE usa uma expressão de caminho
JSON para extrair uma parte dos dados fornecidos
para usar como um padrão de linha para a visão construída.
Cada valor SQL/JSON fornecido pelo padrão de
linha serve como fonte para uma linha separada na visão construída.
Para dividir o padrão de linhas em colunas, a função
JSON_TABLE fornece a cláusula
COLUMNS que define o esquema da visão criada.
Para cada coluna, pode ser especificada uma expressão de caminho
JSON separada para ser avaliada em relação ao
padrão da linha, a fim de obter um valor SQL/JSON
que se tornará o valor da coluna especificada em uma determinada
linha de saída.
Os dados JSON armazenados em um nível aninhado
do padrão de linha podem ser extraídos usando a cláusula
NESTED PATH (caminho aninhado).
Cada cláusula NESTED PATH pode ser usada para
gerar uma ou mais colunas usando os dados de um nível aninhado do
padrão de linha.
Estas colunas podem ser especificadas usando uma cláusula
COLUMNS, que é semelhante à cláusula
COLUMNS de nível superior.
As linhas construídas a partir de NESTED COLUMNS
são chamadas de child rows (linhas filhas)
e são unidas à linha construída a partir das colunas especificadas
na cláusula mãe COLUMNS para obter a linha na
visão final.
As próprias colunas filhas podem conter uma especificação de
NESTED PATH, permitindo assim extrair dados
localizados em níveis de aninhamento arbitrários.
As colunas produzidas por múltiplos NESTED PATH
no mesmo nível são consideradas siblings
(irmãs) umas das outras e suas linhas, após serem unidas à linha mãe,
são combinadas usando UNION.
As linhas produzidas pela função JSON_TABLE são
unidas lateralmente à linha que as gerou, portanto, não é necessário
unir explicitamente a visão construída com a tabela original que
contém os dados JSON.
A sintaxe é:
JSON_TABLE (
context_item, path_expression [ AS json_path_name ] [ PASSING { value AS varname } [, ...] ]
COLUMNS ( json_table_column [, ...] )
[ { ERROR | EMPTY [ARRAY]} ON ERROR ]
)
one json_table_column é:
name FOR ORDINALITY
| name type
[ FORMAT JSON [ENCODING UTF8]]
[ PATH path_expression ]
[ { WITHOUT | WITH { CONDITIONAL | [UNCONDITIONAL] } } [ ARRAY ] WRAPPER ]
[ { KEEP | OMIT } QUOTES [ ON SCALAR STRING ] ]
[ { ERROR | NULL | EMPTY { [ARRAY] | OBJECT } | DEFAULT expression } ON EMPTY ]
[ { ERROR | NULL | EMPTY { [ARRAY] | OBJECT } | DEFAULT expression } ON ERROR ]
| name type EXISTS [ PATH path_expression ]
[ { ERROR | TRUE | FALSE | UNKNOWN } ON ERROR ]
| NESTED [ PATH ] path_expression [ AS json_path_name ] COLUMNS ( json_table_column [, ...] )
Cada elemento da sintaxe é descrito com mais detalhes abaixo.
context_item, path_expression [ AS json_path_name ] [ PASSING { value AS varname } [, ...]]
context_item especifica o documento
de entrada a ser consultado,
path_expression é uma expressão de caminho
SQL/JSON que define a consulta, e
json_path_name é um nome opcional para
path_expression.
A cláusula opcional PASSING fornece valores de
dados para as variáveis mencionadas em
path_expression.
O resultado da avaliação dos dados de entrada usando os elementos
mencionados anteriormente é chamado de
row pattern (padrão de linha), que é usado
como fonte para os valores das linhas na visão construída.
COLUMNS ( json_table_column [, ...] )
A cláusula COLUMNS que define o esquema da
visão construída.
Nesta cláusula, é possível especificar que cada coluna seja
preenchida com um valor SQL/JSON obtido pela
aplicação de uma expressão de caminho JSON
ao padrão de linha.
json_table_column possui as seguintes
variantes:
name FOR ORDINALITY
Adiciona uma coluna de ordinalidade que fornece numeração
sequencial de linhas a partir de 1.
Cada NESTED PATH (veja abaixo) obtém seu próprio
contador para quaisquer colunas de ordinalidade aninhadas.
name type
[FORMAT JSON [ENCODING UTF8]]
[ PATH path_expression ]
Insere o valor SQL/JSON obtido pela aplicação de
path_expression ao padrão de linha na
linha de saída da visão, após convertê-lo para o
type especificado.
Especificar FORMAT JSON deixa explícito que é
esperado que o valor seja um objeto do tipo de dados
json válido.
Só faz sentido especificar FORMAT JSON se
type for um entre bpchar,
bytea, character varying, name,
json, jsonb, text, ou um
domínio sobre estes tipos de dados.
Opcionalmente, podem ser especificadas as cláusulas
WRAPPER e QUOTES
para formatar a saída.
Note que especificar OMIT QUOTES se sobrepõe a
FORMAT JSON se este também for especificado,
porque literais sem aspas não constituem valores do tipo de dados
json válidos.
Opcionalmente, podem ser usadas as cláusulas
ON EMPTY e ON ERROR
para especificar se deve ser gerados um erro ou retornado o valor
especificado quando o resultado da avaliação do caminho
JSON estiver vazio, e quando ocorrer um erro
durante a avaliação do caminho JSON ou ao
converter o valor SQL/JSON para o tipo de dados
especificado, respectivamente.
O padrão para ambos é retornar o valor NULL.
Esta cláusula é internamente transformada e tem a mesma semântica
das funções JSON_VALUE e
JSON_QUERY.
Este último caso se aplica se o tipo de dados especificado não for
um tipo de dados escalar, ou se uma das cláusulas
FORMAT JSON, WRAPPER ou
QUOTES estiver presente.
name type
EXISTS [ PATH path_expression ]
Insere o valor booleano obtido pela aplicação de
path_expression ao padrão de linha na
linha de saída da visão, após convertê-la para o
type especificado.
O valor corresponde à aplicação da expressão PATH
ao padrão da linha, retornando valores ou não.
O type especificado deve possuir uma
conversão a partir do tipo de dados boolean.
Opcionalmente, pode ser usada a cláusula ON ERROR
para especificar se deve ser gerado um erro ou retornado o valor
especificado quando for encontrado um erro durante a avaliação do
arquivo JSON ou durante a conversão do valor
SQL/JSON para o tipo de dados especificado.
O padrão é retornar o valor booleano FALSE.
Esta cláusula é transformada internamente e tem a mesma semântica
que JSON_EXISTS.
NESTED [ PATH ] path_expression [ AS json_path_name ]
COLUMNS ( json_table_column [, ...] )
Extrai valores SQL/JSON de níveis aninhados
do padrão de linha, gera uma ou mais colunas conforme definido
pela subcláusula COLUMNS e insere os valores
SQL/JSON extraídos nessas colunas.
A expressão json_table_column na
subcláusula COLUMNS usa a mesma sintaxe da
cláusula COLUMNS mãe.
A sintaxe NESTED PATH é recursiva,
assim é possível percorrer vários níveis aninhados especificando
várias subcláusulas NESTED PATH umas dentro
das outras.
Permite desaninhar a hierarquia de objetos e matrizes
JSON em uma única invocação de função,
em vez de encadear várias expressões JSON_TABLE
em uma instrução SQL.
Em cada variante de json_table_column
descrita acima, se a cláusula PATH for omitida,
será usada a expressão de caminho
$.,
onde namename é o nome da coluna fornecido.
AS json_path_name
A cláusula opcional json_path_name serve
como identificador para a path_expression
fornecida.
O nome deve ser único e distinto dos nomes das colunas.
ERROR | EMPTY } ON ERROR
Pode ser usada a cláusula opcional ON ERROR
para especificar como lidar com erros ao avaliar a
path_expression de nível superior.
Deve ser usado ERROR se for desejado
que sejam gerados erros ou EMPTY para retornar
uma tabela vazia, ou seja, uma tabela contendo 0 linhas.
Note que esta cláusula não afeta os erros que ocorrem ao avaliar
colunas, cujo comportamento depende de a cláusula
ON ERROR estar especificada para uma determinada
coluna.
Exemplos
Nos exemplos que a seguir, será utilizada a seguinte tabela contendo dados JSON:
CREATE TABLE my_films ( js jsonb );
INSERT INTO my_films VALUES (
'{ "favorites" : [
{ "kind" : "comedy", "films" : [
{ "title" : "Bananas",
"director" : "Woody Allen"},
{ "title" : "The Dinner Game",
"director" : "Francis Veber" } ] },
{ "kind" : "horror", "films" : [
{ "title" : "Psycho",
"director" : "Alfred Hitchcock" } ] },
{ "kind" : "thriller", "films" : [
{ "title" : "Vertigo",
"director" : "Alfred Hitchcock" } ] },
{ "kind" : "drama", "films" : [
{ "title" : "Yojimbo",
"director" : "Akira Kurosawa" } ] }
] }');
A consulta a seguir mostra como usar a função
JSON_TABLE para transformar os objetos
JSON da tabela my_films
em uma visão contendo colunas para as chaves
kind, title e
director presentes no JSON
original, juntamente com uma coluna de ordinalidade:
SELECT jt.* FROM my_films, JSON_TABLE (js, '$.favorites[*]' COLUMNS ( id FOR ORDINALITY, kind text PATH '$.kind', title text PATH '$.films[*].title' WITH WRAPPER, director text PATH '$.films[*].director' WITH WRAPPER)) AS jt;
id | kind | title | director ----+----------+--------------------------------+---------------------------------- 1 | comedy | ["Bananas", "The Dinner Game"] | ["Woody Allen", "Francis Veber"] 2 | horror | ["Psycho"] | ["Alfred Hitchcock"] 3 | thriller | ["Vertigo"] | ["Alfred Hitchcock"] 4 | drama | ["Yojimbo"] | ["Akira Kurosawa"] (4 linhas)
A seguir, é apresentada uma versão modificada da consulta acima
para mostrar o uso de argumentos PASSING
no filtro especificado na expressão do caminho
JSON de nível superior e as várias opções
para as colunas individuais:
SELECT jt.* FROM
my_films,
JSON_TABLE (js, '$.favorites[*] ? (@.films[*].director == $filter)'
PASSING 'Alfred Hitchcock' AS filter
COLUMNS (
id FOR ORDINALITY,
kind text PATH '$.kind',
title text FORMAT JSON PATH '$.films[*].title' OMIT QUOTES,
director text PATH '$.films[*].director' KEEP QUOTES)) AS jt;
id | kind | title | director ----+----------+---------+-------------------- 1 | horror | Psycho | "Alfred Hitchcock" 2 | thriller | Vertigo | "Alfred Hitchcock" (2 linhas)
A seguir é apresentada uma versão modificada da consulta acima
para mostrar o uso de NESTED PATH para preencher
as colunas title e director,
ilustrando como elas são unidas às colunas mãe
id e kind:
SELECT jt.* FROM
my_films,
JSON_TABLE ( js, '$.favorites[*] ? (@.films[*].director == $filter)'
PASSING 'Alfred Hitchcock' AS filter
COLUMNS (
id FOR ORDINALITY,
kind text PATH '$.kind',
NESTED PATH '$.films[*]' COLUMNS (
title text FORMAT JSON PATH '$.title' OMIT QUOTES,
director text PATH '$.director' KEEP QUOTES))) AS jt;
id | kind | title | director ----+----------+---------+-------------------- 1 | horror | Psycho | "Alfred Hitchcock" 2 | thriller | Vertigo | "Alfred Hitchcock" (2 linhas)
A seguir é apresentada a mesma consulta, porém sem o filtro no caminho raiz:
SELECT jt.* FROM
my_films,
JSON_TABLE ( js, '$.favorites[*]'
COLUMNS (
id FOR ORDINALITY,
kind text PATH '$.kind',
NESTED PATH '$.films[*]' COLUMNS (
title text FORMAT JSON PATH '$.title' OMIT QUOTES,
director text PATH '$.director' KEEP QUOTES))) AS jt;
id | kind | title | director ----+----------+-----------------+-------------------- 1 | comedy | Bananas | "Woody Allen" 1 | comedy | The Dinner Game | "Francis Veber" 2 | horror | Psycho | "Alfred Hitchcock" 3 | thriller | Vertigo | "Alfred Hitchcock" 4 | drama | Yojimbo | "Akira Kurosawa" (5 linhas)
A seguir é apresentada outra consulta usando um objeto
do tipo de dados JSON diferente como entrada.
Ela mostra a junção de irmãos
(sibling join/UNION) entre os
caminhos aninhados (NESTED)
$.movies[*] e $.books[*],
e também o uso da coluna FOR ORDINALITY
nos níveis aninhados (NESTED)
(colunas movie_id, book_id
e author_id):
SELECT * FROM JSON_TABLE (
'{"favorites":
[{"movies":
[{"name": "One", "director": "John Doe"},
{"name": "Two", "director": "Don Joe"}],
"books":
[{"name": "Mystery", "authors": [{"name": "Brown Dan"}]},
{"name": "Wonder", "authors": [{"name": "Jun Murakami"}, {"name":"Craig Doe"}]}]
}]}'::json, '$.favorites[*]'
COLUMNS (
user_id FOR ORDINALITY,
NESTED '$.movies[*]'
COLUMNS (
movie_id FOR ORDINALITY,
mname text PATH '$.name',
director text),
NESTED '$.books[*]'
COLUMNS (
book_id FOR ORDINALITY,
bname text PATH '$.name',
NESTED '$.authors[*]'
COLUMNS (
author_id FOR ORDINALITY,
author_name text PATH '$.name'))));
user_id | movie_id | mname | director | book_id | bname | author_id | author_name
---------+----------+-------+----------+---------+---------+-----------+--------------
1 | 1 | One | John Doe | | | |
1 | 2 | Two | Don Joe | | | |
1 | | | | 1 | Mystery | 1 | Brown Dan
1 | | | | 2 | Wonder | 1 | Jun Murakami
1 | | | | 2 | Wonder | 2 | Craig Doe
(5 linhas)