L'interrogation à l'intérieur de Postgres tableaux JSON
Comment feriez-vous à la recherche d'un élément dans un tableau stocké dans un json
de la colonne? (Mise à jour: voir Aussi la mise à jour 9.4 réponse pour jsonb
colonnes.)
Si j'ai un document JSON comme ça, stockée dans un json
colonne nommée blob
:
{"name": "Wolf",
"ids": [185603363281305602,185603363289694211]}
ce que j'aimerais être capable de faire quelque chose comme:
SELECT * from "mytable" WHERE 185603363289694211 = ANY("blob"->'ids');
et obtenir toutes les lignes correspondantes de sortir. Mais cela ne fonctionne pas parce que "blob"->'ids'
renvoie du JSON valeurs, pas Postgres tableaux.
J'aimerais aussi créer un index sur la personne de l'IDs, si c'est possible.
Vous devez vous connecter pour publier un commentaire.
Suivantes réponse originale à cette question ne s'applique que pour Postgresql 9.3. Pour un Postgresql 9.4 réponse, voir la mise à Jour ci-dessous.
Cela s'appuie sur Erwin est référencé réponses, mais est un peu plus explicite à cette question.
Les Id dans ce cas sont
bigint
s, donc créer une fonction d'aide pour la conversion d'un tableau JSON pour une Postgresbigint
tableau:Nous pourrions simplement avoir facilement (et peut-être plus re-usably) a retourné une
text
tableau ici à la place. Je soupçonne l'indexation surbigint
est beaucoup plus rapide quetext
mais je vais avoir un moment difficile de trouver des preuves en ligne pour accompagner cela.Pour la construction de l'index:
De l'interrogation, de ce qui fonctionne et utilise l'index:
Faisant cela fonctionnera aussi pour les interroger, mais il n'utilise pas l'index:
Mise à jour de 9,4
Postgresql 9.4 introduit la
jsonb
type. C'est un bon AFIN de répondre à propos dejsonb
et quand vous devriez l'utiliser surjson
. En bref, si jamais vous êtes en interrogeant le JSON, vous devez utiliserjsonb
.Si vous construisez votre colonne comme
jsonb
, vous pouvez utiliser cette requête:La
@>
est Postgres' opérateur contient, documenté pourjsonb
ici.Grâce à Alain répondre pour avoir porté à mon attention.
bigint
est généralement plus rapide que le traitement de latext
. Fait aussi pour un petits index, mais de simplifierelem::text::bigint
àelem::bigint
. BTW, pas besoin de guillemets autour de parfaitement identificateurs valides dans Postgres.json
directement àbigint
ne fonctionne pas. Je dois passer partext
premier.ANY(json_array_bigint("blob"->'ids');
--> il y a un)
manquant à la finD'abord, essayez de l'opérateur
->>
au lieu de->
à la bande JSON couche à partir du tableau de la valeur.Prochain, le requête peut fonctionner comme ceci:
Comment faire j'ai une requête à l'aide de champs à l'intérieur de la nouvelle PostgreSQL JSON type de données?
Et indexation pourrait fonctionner comme ceci:
Indice pour trouver un élément dans un tableau JSON
Je sais, ça fait un moment...
Dans postgresql-9.5, il est maintenant possible de faire des requêtes facilement.
Je pense que vous devriez utiliser un
jsonb
champ au lieu et vous pouvez l'index par la suite.@>
ne fonctionne que surjsonb
colonnes, pasjson
colonnes. (C'est probablement pas un problème, je ne peux pas penser à des situations dans lesquelles vous choisissezjson
surjsonb
, mais cette question a été initialement demandé Postgresql 9.3, qui n'a pas encorejsonb
)SELECT * from "mytable" WHERE blob @> '{"ids": [185603363281305602]}'
;