Como faço para consultar usando campos dentro do novo tipo de dados JSON do PostgreSQL?

216

Estou procurando alguns documentos e / ou exemplos para as novas funções JSON no PostgreSQL 9.2.

Especificamente, considerando uma série de registros JSON:

[
  {name: "Toby", occupation: "Software Engineer"},
  {name: "Zaphod", occupation: "Galactic President"}
]

Como eu escreveria o SQL para encontrar um registro pelo nome?

Em baunilha SQL:

SELECT * from json_data WHERE "name" = "Toby"

O manual oficial do desenvolvedor é bastante escasso:

Atualização I

Reuni uma essência detalhando o que é atualmente possível com o PostgreSQL 9.2 . Usando algumas funções personalizadas, é possível fazer coisas como:

SELECT id, json_string(data,'name') FROM things
WHERE json_string(data,'name') LIKE 'G%';

Atualização II

Agora mudei minhas funções JSON para seu próprio projeto:

PostSQL - um conjunto de funções para transformar o PostgreSQL e o PL / v8 em um incrível repositório de documentos JSON

Toby Hede
fonte
3
Recentemente, encontrei este post de Matt Schinckel, que explica detalhadamente a consulta ao JSON no PostgreSQL schinckel.net/2014/05/25/querying-json-in-postgres
knowbody
1
@knowbody Este post é sobre consulta ao JSONB, que é bem diferente do JSON. Meu mal por não deixar isso mais claro no post.
Matthew Schinckel

Respostas:

177

Postgres 9.2

Cito Andrew Dunstan na lista pgsql-hackers :

Em algum momento, possivelmente haverá algumas funções de processamento de json (em oposição à produção de json), mas não na 9.2.

Não o impede de fornecer um exemplo de implementação no PLV8 que deve resolver seu problema.

Postgres 9.3

Oferece um arsenal de novas funções e operadores para adicionar "json-processing".

A resposta para a pergunta original no Postgres 9.3:

SELECT *
FROM   json_array_elements(
  '[{"name": "Toby", "occupation": "Software Engineer"},
    {"name": "Zaphod", "occupation": "Galactic President"} ]'
  ) AS elem
WHERE elem->>'name' = 'Toby';

Exemplo avançado:

Para tabelas maiores, você pode adicionar um índice de expressão para aumentar o desempenho:

Postgres 9.4

Adiciona jsonb(b para "binário", os valores são armazenados como tipos nativos do Postgres) e ainda mais funcionalidade para os dois tipos. Além dos índices de expressão mencionados acima, jsonbtambém suporta índices GIN, btree e hash , sendo o GIN o mais potente deles.

O manual chega a sugerir:

Em geral, a maioria dos aplicativos deve preferir armazenar dados JSON como jsonb , a menos que haja necessidades bastante especializadas, como suposições herdadas sobre a ordem de chaves de objetos.

Negrito ênfase minha.

O desempenho se beneficia de melhorias gerais nos índices GIN.

Postgres 9.5

jsonbFunções e operadores completos . Adicione mais funções para manipular jsonbno local e para exibição.

Erwin Brandstetter
fonte
1
Obrigado, eu deparei com problemas de tipo muito rápido usando a abordagem PLV8. Parece promissor, mas não é realmente utilizável no momento.
Toby Hede
@TobyHede: Acho que teremos que esperar pelo 9.3 então.
Erwin Brandstetter
1
@ JoeShaw: Obrigado, atualizei de acordo e adicionei um link para o Wiki do Postgres.
Erwin Brandstetter 10/09
@ErwinBrandstetter se estou procurando WHERE elem - >> 'correct' = 'TRUE'; e o JSON fica assim: "correto": "VERDADEIRO", qual é a maneira correta de consultar termos lógicos?
Shiraj 18/01/19
@Shiraj: Por favor, faça as novas perguntas como pergunta . Comentários não são o lugar.
Erwin Brandstetter
87

Com o Postgres 9.3+, basta usar o ->operador. Por exemplo,

SELECT data->'images'->'thumbnail'->'url' AS thumb FROM instagram;

consulte http://clarkdave.net/2013/06/what-can-you-do-with-postgresql-and-json/ para obter alguns bons exemplos e um tutorial.

Meekohi
fonte
2
No exemplo acima, você deve ter um campo chamado datacom um documento JSON: {images:{thumbnail:{url:'thumbnail.jpg'}}}. Informe qual é a aparência dos seus dados e qual consulta está falhando.
Meekohi 27/03
6
Como você pode consultar se existe uma matriz? Eu vejo o operador # >>, mas nenhuma pista de como usá-lo!
Mohamed El Mahallawy
Nesta consulta selecionada, posso usar curinga? IeSELECT data->'%'->'thumbnail'->'url' AS thumb FROM instagram;
Bharat
@ A resposta de Meekohi funciona bem: especificamente, eu não precisava ::jsonconforme descrito em outros posts. Observe também que o ->operador lançará um erro se você tentar acessar uma propriedade que não existe (por exemplo, se você tiver escalonado o JSON):ERROR: column "jsonPropertyYouWant" does not exist
The Red Pea
19

Com o postgres 9.3, use -> para acessar objetos. 4 exemplo

seed.rb

se = SmartElement.new
se.data = 
{
    params:
    [
        {
            type: 1,
            code: 1,
            value: 2012,
            description: 'year of producction'
        },
        {
            type: 1,
            code: 2,
            value: 30,
            description: 'length'
        }
    ]
}

se.save

trilhos c

SELECT data->'params'->0 as data FROM smart_elements;

retorna

                                 data
----------------------------------------------------------------------
 {"type":1,"code":1,"value":2012,"description":"year of producction"}
(1 row)

Você pode continuar aninhando

SELECT data->'params'->0->'type' as data FROM smart_elements;

Retorna

 data
------
 1
(1 row)
joseAndresGomezTovar
fonte