¿Cómo hago consultas usando campos dentro del nuevo tipo de datos PostgreSQL JSON?

216

Estoy buscando algunos documentos y / o ejemplos para las nuevas funciones JSON en PostgreSQL 9.2.

Específicamente, dada una serie de registros JSON:

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

¿Cómo escribiría el SQL para encontrar un registro por nombre?

En vainilla SQL:

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

El manual de desarrollo oficial es bastante escaso:

Actualización I

He reunido una esencia que detalla lo que actualmente es posible con PostgreSQL 9.2 . Usando algunas funciones personalizadas, es posible hacer cosas como:

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

Actualización II

Ahora he movido mis funciones JSON a su propio proyecto:

PostSQL : un conjunto de funciones para transformar PostgreSQL y PL / v8 en una increíble tienda de documentos JSON

Toby Hede
fuente
3
Recientemente encontré esta publicación de blog de Matt Schinckel, que explica en detalle la consulta de JSON en PostgreSQL schinckel.net/2014/05/25/querying-json-in-postgres
knowbody
1
@knowbody Esta publicación en realidad se trata de consultar JSONB, que es bastante diferente de JSON. Mi mal por no aclarar eso en la publicación.
Matthew Schinckel

Respuestas:

177

Postgres 9.2

Cito a Andrew Dunstan en la lista de hackers pgsql :

En algún momento, posiblemente habrá algunas funciones de procesamiento de json (en oposición a la producción de json), pero no en 9.2.

No le impide proporcionar una implementación de ejemplo en PLV8 que debería resolver su problema.

Postgres 9.3

Ofrece un arsenal de nuevas funciones y operadores para agregar "procesamiento json".

La respuesta a la pregunta original en Postgres 9.3:

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

Ejemplo avanzado:

Para tablas más grandes, es posible que desee agregar un índice de expresión para aumentar el rendimiento:

Postgres 9.4

Agrega jsonb(b para "binario", los valores se almacenan como tipos nativos de Postgres) y aún más funcionalidad para ambos tipos. Además de los índices de expresión mencionados anteriormente, jsonbtambién admite índices GIN, btree y hash , siendo GIN el más potente de estos.

El manual llega a sugerir:

En general, la mayoría de las aplicaciones deberían preferir almacenar datos JSON como jsonb , a menos que haya necesidades bastante especializadas, como los supuestos heredados sobre el pedido de claves de objeto.

El énfasis en negrita es mío.

El rendimiento se beneficia de las mejoras generales de los índices GIN.

Postgres 9.5

jsonbFunciones completas y operadores. Agregue más funciones para manipular jsonben el lugar y para mostrar.

Erwin Brandstetter
fuente
1
Gracias, me he encontrado con problemas de tipo muy rápido usando el enfoque PLV8. Parece prometedor, pero no realmente utilizable en este momento.
Toby Hede
@TobyHede: Supongo que tendremos que esperar 9.3 entonces.
Erwin Brandstetter
1
@ JoeShaw: Gracias, actualicé en consecuencia y agregué un enlace al Postgres Wiki.
Erwin Brandstetter
@ErwinBrandstetter si estoy buscando WHERE elem - >> 'correct' = 'TRUE'; y el JSON se ve así: "correcto": "VERDADERO", ¿cuál es la forma correcta de consultar términos lógicos?
Shiraj
@ Shiraj: por favor haga las nuevas preguntas como pregunta . Los comentarios no son el lugar.
Erwin Brandstetter
87

Con Postgres 9.3+, solo usa el ->operador. Por ejemplo,

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

ver http://clarkdave.net/2013/06/what-can-you-do-with-postgresql-and-json/ para ver algunos buenos ejemplos y un tutorial.

Meekohi
fuente
2
En el ejemplo anterior se debe tener un campo llamado datacon un documento JSON: {images:{thumbnail:{url:'thumbnail.jpg'}}}. Háganos saber cómo se ven sus datos y qué consulta está fallando.
Meekohi
66
¿Cómo se puede consultar si hay una matriz? ¡Veo el operador # >> pero no tengo idea de cómo usarlo!
Mohamed El Mahallawy
En esta consulta de selección, ¿puedo usar comodines? Es decirSELECT data->'%'->'thumbnail'->'url' AS thumb FROM instagram;
Bharat
La respuesta de @ Meekohi funciona bien: específicamente no la necesitaba ::jsoncomo se describe en otras publicaciones. También tenga en cuenta que el ->operador arrojará un error si intenta acceder a una propiedad que no existe (es decir, si ha escalonado JSON):ERROR: column "jsonPropertyYouWant" does not exist
The Red Pea
19

Con postgres 9.3 use -> para acceder a objetos. 4 ejemplo

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

rieles c

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

devoluciones

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

Puedes continuar anidando

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

regreso

 data
------
 1
(1 row)
joseAndresGomezTovar
fuente