Cette section décrit :
les fonctions et opérateurs pour traiter et créer des données JSON
le langage de chemin SQL/JSON
Pour en savoir plus sur le standard SQL/JSON, voir [sqltr-19075-6]. Pour des détails sur les types JSON supportés dans PostgreSQL, voir Section 8.14.
Tableau 9.44 affiche les opérateurs
disponibles pour les types de données JSON (voir Section 8.14). De plus, les opérateurs de comparaison
habituels indiqués dans Tableau 9.1
sont disponibles pour le type jsonb
, mais pas pour le type
json
. Les opérateurs de comparaison suivent les règles de tri
des opérateurs B-tree indiqués dans Section 8.14.4.
Voir aussi Section 9.21 pour la fonction
d'agrégat json_agg
qui agrège les valeurs
d'enregistrements sous la forme d'un JSON, pour la fonction d'agrégat
json_object_agg
qui agrège des paires de valeurs dans
un objet JSON, et leurs équivalents jsonb
, à savoir
jsonb_agg
et jsonb_object_agg
.
Tableau 9.44. Opérateurs json
et jsonb
Opérateur Description Exemple(s) |
---|
Extrait le
|
Extrait le champ objet JSON avec la clé donnée.
|
Extrait le
|
Extrait le champ objet JSON d'après la clé donnée, comme
|
Extrait le sous-objet JSON d'un chemin spécifié, où les éléments du chemin peuvent être soit les clés d'un champ, soit les indices d'un tableau.
|
Extrait le sous-objet JSON au chemin spécifié avec
|
Les opérateurs d'extraction champ/élément/chemin renvoient NULL, plutôt qu'une erreur, si l'entrée JSON n'a pas la bonne structure correspondant à la requête ; par exemple si la clé ou l'élément du tableau n'existe pas.
Quelques opérateurs supplémentaires existent seulement pour le type
jsonb
, comme indiqué dans Tableau 9.45. Section 8.14.4
décrit comment ces opérateurs peuvent être utilisés pour rechercher
efficacement les données jsonb
indexées.
Tableau 9.45. Opérateurs jsonb
supplémentaires
Opérateur Description Exemple(s) |
---|
Est-ce que la première valeur JSON contient la seconde ? (Voir Section 8.14.3 pour les détails sur la notion de contenu.)
|
Est-ce que la première valeur JSON est contenue dans la seconde ?
|
Est-ce que la chaîne de caractères existe comme clé de haut niveau ou élément de tableau dans la valeur JSON ?
|
Est-ce qu'une des chaînes du tableau de texte existe comme clé de haut niveau ou comme élément de tableau ?
|
Est-ce que toutes les chaînes du tableau de texte existent comme clés de haut niveau ou comme éléments de tableau ?
|
Concatène deux valeurs
Pour concaténer un tableau à un autre tableau dans une entrée unique, il faut l'envelopper dans une couche supplémentaire de tableau, par exemple :
|
Supprime une clé (et sa valeur) à partir d'un objet JSON, ou les valeurs correspondantes de chaînes à partir d'un tableau JSON.
|
Supprime toutes les clés ou tous les éléments de tableau correspondant à partir de l'opérande gauche.
|
Supprime l'élément de tableau pour l'index spécifié (les nombres négatifs se décomptent à partir de la fin). Renvoie une erreur si la valeur JSON n'est pas un tableau.
|
Supprime le champ ou l'élément de tableau sur le chemin indiqué, les éléments du chemin pouvant être soit des clés de champ, soit des indices de tableau.
|
Est-ce que le chemin JSON renvoie tout élément pour la valeur JSON spécifiée ?
|
Renvoie le résultat d'une vérification de prédicat du chemin JSON pour
la valeur JSON indiquée. Seul le premier élément du résultat est pris
en compte. Si le résultat n'est pas un booléen, alors
|
Les opérateurs @?
et @@
du type
jsonpath
suppriment les erreurs suivantes : champ objet
ou élément de tableau manquant, type d'élément JSON inattendu, erreurs de
date/heure ou de numérique. Les fonctions relatives à
jsonpath
décrites ci-dessous peuvent aussi supprimer ce type
d'erreurs à la demande. Ce comportement pourrait être utile lors de la
recherche de collections de documents JSON de différentes structures.
Tableau 9.46 montre les fonctions
disponibles pour construire des valeurs json
et
jsonb
.
Tableau 9.46. Fonctions de création de JSON
Fonction Description Exemple(s) |
---|
Convertit toute valeur SQL en
|
Convertit un tableau SQL en tableau JSON. Le comportement est le même
que
|
Convertit une valeur composite SQL en objet JSON. Le comportement est
le même que
|
Construit un tableau JSON avec des types potentiellement hétérogènes à
partir d'une liste d'arguments de longueur variable. Chaque argument
est converti avec la fonction
|
Construit un objet JSON à partir d'une liste d'arguments de longueur
indéfinie. Par convention, la liste d'arguments consiste en des clés
et valeurs en alternance. Les arguments clés sont convertis en
texte ; les arguments valeurs sont convertis via les fonctions
|
Construit un objet JSON à partir d'un tableau de texte. Le tableau doit avoir soit exactement une dimension avec un nombre pair de membres, auquel cas ils sont pris comme des paires alternantes clé/valeur, ou deux dimensions de telle façon que le tableau interne a exactement deux éléments, pris comme une paire clé/valeur. Toutes les valeurs sont converties en chaîne JSON.
|
Cette forme de
|
Tableau 9.47 montre les fonctions
disponibles pour le traitement de valeurs json
et
jsonb
.
Tableau 9.47. Fonctions de traitement JSON
Fonction Description Exemple(s) |
---|
Étend le tableau JSON de haut niveau en un ensemble de valeurs JSON.
value ----------- 1 true [2,false]
|
Étend le tableau JSON de haut niveau en un ensemble de valeurs de type
value ----------- foo bar
|
Renvoie le nombre d'éléments dans le tableau JSON de haut niveau.
|
Étend l'objet JSON de haut niveau en un ensemble de paires clé/valeur.
key | value -----+------- a | "foo" b | "bar"
|
Étend l'objet JSON de haut niveau en un ensemble de paires clé/valeur.
Les
key | value -----+------- a | foo b | bar
|
Extrait un sous-objet JSON au chemin spécifié. (Ceci est
fonctionnellement équivalent à l'opérateur
|
Extrait le sous-objet JSON au chemin spécifié sous la forme d'un
|
Renvoie l'ensemble de clés dans l'objet JSON de haut niveau.
json_object_keys ------------------ f1 f2
|
Étend l'objet JSON de haut niveau en une ligne ayant le type composite
de l'argument Pour convertir une valeur JSON au type SQL d'une colonne en sortie, les règles suivantes sont appliquées sur cette séquence :
Bien que l'exemple ci-dessous utilise une valeur constante JSON, une
utilisation typique serait de référencer une colonne
a | b | c ---+-----------+------------- 1 | {2,"a b"} | (4,"a b c")
|
Étend le tableau JSON de haut niveau composé d'objets en un ensemble
de lignes ayant le type composite de l'argument
a | b ---+--- 1 | 2 3 | 4
|
Étend l'objet JSON de haut niveau en une ligne ayant le type composite
défini par une clause
a | b | c | d | r ---+---------+---------+---+--------------- 1 | [1,2,3] | {1,2,3} | | (123,"a b c")
|
Étend le tableau JSON de haut niveau composé d'objets en un ensemble
de lignes ayant le type composite défini par une clause
a | b ---+----- 1 | foo 2 |
|
Renvoie
|
Si
|
Renvoie
|
Supprime tous les champs objets ayant des valeurs NULL à partir de la valeur JSON donnée, de façon récurvise. Les valeurs NULL qui ne sont pas des champs objets ne sont pas touchées.
|
Vérifie si le chemin JSON renvoie des éléments de la valeur JSON
spécifiée. Si l'argument
|
Renvoie le résultat de la vérification d'un prédicat de chemin JSON
pour la valeur JSON spécifiée. Seul le premier élément du résultat est
pris en compte. Si le résultat n'est pas un booléen, alors
|
Renvoie tous les éléments JSON renvoyés par le chemin JSON pour la
valeur JSON spécifiée. Les arguments optionnels
jsonb_path_query ------------------ 2 3 4
|
Renvoie tous les éléments JSON renvoyés par le chemin JSON pour la
valeur JSON spécifiée, sous la forme d'un tableau JSON. Les arguments
optionnels
|
Renvoie le premier élément JSON renvoyé par le chemin JSON pour la
valeur JSON spécifiée. Renvoie
|
Ces fonctions agissent comme leurs homologues décrits ci-dessus sans
le suffixe
|
Convertit la valeur JSON donnée en un texte proprement indenté.
[ { "f1": 1, "f2": null }, 2 ]
|
Renvoie le type de la valeur JSON de haut niveau sous la forme d'une
chaîne de caractères. Les types possibles sont
|
Les expressions de chemin SQL/JSON indiquent les éléments à récupérer à
partir de données JSON, similaires aux expressions XPath utilisées pour
l'accès SQL au XML. Dans PostgreSQL, les
expressions de chemin sont implémentées sous la forme du type de données
jsonpath
et peuvent utiliser tout élément décrit dans Section 8.14.7.
Les fonctions et opérateurs de requêtes JSON passent l'expression de chemin fournie au moteur de chemin pour évaluation. Si l'expression correspond à la donnée JSON requêtée, l'élément JSON correspondant ou l'ensemble d'éléments est renvoyé. Les expressions de chemin sont écrites dans le langage de chemin SQL/JSON et peuvent inclure les expressions et fonctions arithmétiques.
Une expression de chemin consiste en une séquence d'éléments autorisés par
le type de données jsonpath
. L'expression de chemin est
habituellement évaluée de gauche à droite, mais vous pouvez utiliser les
parenthèses pour modifier l'ordre des opérations. Si l'évaluation réussit,
une séquence d'éléments JSON est produite et le résultat de l'évaluation
est renvoyé à la fonction de requête JSON qui termine le traitement
indiqué.
Pour faire référence à la valeur JSON en cours de requêtage
(l'élément de contexte), utilisez la variable
$
dans l'expression de chemin. Elle peut être suivie par
un ou plusieurs opérateurs
d'accesseurs, qui descendent dans la structure JSON, étape par
étape, pour récupérer les sous-éléments de l'élément de contexte. Chaque
opérateur qui suit traite le résultat de l'étape d'évaluation précédente.
Par exemple, supposez que vous ayez certaines données JSON à partir d'un traqueur GPS que vous voulez analyser, tel que :
{ "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 } ] } }
Pour récupérer les segments de piste disponibles, vous avez besoin
d'utiliser l'opérateur d'accesseur
.
pour descendre à travers
les objets JSON tout autour :
key
$.track.segments
Pour récupérer le contenu d'un tableau, vous utilisez typiquement
l'opérateur [*]
. Par exemple, le chemin suivant renverra
les coordonnées d'emplacement pour tous les segments de piste
disponibles :
$.track.segments[*].location
Pour renvoyer les coordonnées du premier segment seulement, vous pouvez
indiquer l'indice correspondant dans l'opérateur []
.
Rappellez-vous que les indices de tableau JSON commencent à 0 :
$.track.segments[0].location
Le résultat de chaque étape d'évaluation de chemin peut être traité par un
ou plusieurs opérateurs et méthodes jsonpath
, listés dans
Section 9.16.2.2. Chaque nom de méthode
doit être précédé d'un point. Par exemple, vous pouvez obtenir la taille
d'un tableau :
$.track.segments.size()
D'autres exemples d'utilisation d'opérateurs et méthodes
jsonpath
à l'intérieur d'expressions de chemins apparaissent
ci-dessous dans Section 9.16.2.2.
Lors de la définition d'un chemin, vous pouvez aussi utiliser une ou
plusieurs expressions de filtre qui fonctionnent de
façon similaire à la clause WHERE
en SQL. Une expression
de filtre commence avec un point d'interrogation et fournit une condition
entre parenthèses :
? (condition
)
Les expressions de filtre doivent être écrites juste après l'étape
d'évaluation du chemin auquel elles s'appliquent. Le résultat de cette
étape est filtré pour inclure seulement les éléments qui satisfont la
condition fournie. SQL/JSON définit une logique à trois valeurs, donc la
condition peut valoir true
, false
ou
unknown
. La valeur unknown
joue le
même rôle que le NULL
SQL et peut être testée avec le
prédicat is unknown
. Les étapes suivantes d'évaluation
du chemin utilisent seulement les éléments pour lesquels l'expression de
filtre renvoie true
.
Les fonctions et opérateurs pouvant être utilisés dans des expressions de
filtre sont listés dans Tableau 9.49. À l'intérieur d'une
expression de filtre, la variable @
dénote la valeur en
cours de filtrage (un résultat de l'étape de chemin précédente). Vous
pouvez écrire les opérateurs d'accesseurs après @
pour
récupérer les éléments du composant.
Par exemple, supposez que vous vouliez récupérer toutes les valeurs de fréquence cardiaque supérieures à 130. Vous pouvez le faire en utilisant l'expression suivante :
$.track.segments[*].HR ? (@ > 130)
Pour obtenir les heures de début des segments ayant une telle valeur, vous devez filtrer les segments incompatiables avant de renvoyer les heures de début, donc l'expression de filtre est appliquée à l'étape précédente, et le chemin utilisé dans la condition est différent :
$.track.segments[*] ? (@.HR > 130)."start time"
Vous pouvez utiliser plusieurs expressions de filtre en séquence, si nécessaire. Par exemple, l'expression suivante sélectionne les heures de début de tous les segments qui contiennent des emplacements avec les bonnes coordonnées et les valeurs hautes de fréquence cardiaque :
$.track.segments[*] ? (@.location[1] < 13.4) ? (@.HR > 130)."start time"
Il est aussi autorisé d'utiliser des expressions de filtre à différents niveaux de profondeur. L'exemple suivant filtre tout d'abord tous les segments par emplacement, puis renvoie les valeurs hautes de fréquence cardiaque sur ces segments, si disponibles :
$.track.segments[*] ? (@.location[1] < 13.4).HR ? (@ > 130)
Vous pouvez aussi imbriquer les expressions de filtre :
$.track ? (exists(@.segments[*] ? (@.HR > 130))).segments.size()
Cette expression renvoie la taille de la trace si elle contient des segments avec des valeurs hautes de fréquence cardiaque ou, sinon, une séquence vide.
L'implémentation PostgreSQL du langage de chemin SQL/JSON présente les différences suivantes sur le standard SQL/JSON :
Une expression de chemin peut être un prédicat booléen, bien que le
standard SQL/JSON autorise les prédicats uniquement dans les filtres.
Ceci est nécessaire pour l'implémentation de l'opérateur
@@
. Par exemple, l'expression jsonpath
suivante est valide dans PostgreSQL :
$.track.segments[*].HR < 70
Il existe des différences mineures dans l'interprétation des motifs
d'expression rationnelle utilisés dans les filtres
like_regex
, comme décrit dans Section 9.16.2.3.
Quand vous requêtez des données JSON, l'expression de chemin pourrait ne pas correspondre à la structure de données JSON actuelle. Une tentative d'accéder à un membre inexistant d'un objet ou d'un élément d'un tableau résulterait en une erreur de structure. Les expressions de chemin SQL/JSON ont deux modes pour la gestion des erreurs de structure :
lax (permissif, par défaut) -- le moteur de chemin adapte implicitement la donnée requêtée au chemin spécifié. Toute erreur de structure restante est supprimée et convertie en des séquences SQL/JSON vides.
strict -- si une erreur de structure survient, une erreur est levée.
Le mode permissif facilite la correspondance de la structure d'un document JSON et celle d'une expression de chemin si la donnée JSON n'est pas conforme au schéma attendu. Si un opérande ne correspond pas aux demandes d'une opération particulière, il peut être automatiquement intégré à un tableau SQL/JSON ou déballé en convertissant ses éléments en une séquence SQL/JSON avant de réaliser cette opération. De plus, les opérateurs de comparaison déballent automatiquement leurs opérandes dans le mode permissif, donc vous pouvez directement comparer les tableaux SQL/JSON. Un tableau de taille 1 est considéré égal à son seul élément. Le déballage automatique n'est pas réaliser si :
L'expression de chemin contient les méthodes type()
ou size()
qui renvoient respectivement le type et le
nombre d'éléments dans le tableau.
Les données JSON requêtées contiennent des tableaux imbriqués. Dans ce cas, seul le tableau externe est déballé alors que les tableaux internes restent inchangés. De ce fait, le déballage implicite peut seulement descendre d'un niveau à chaque étape d'évaluation du chemin.
Par exemple, lors du requêtage de données GPS ci-dessus, vous pouvez faire abstraction du fait qu'il stocke un tableau de segments en utilisant le mode permissif :
lax $.track.segments.location
Dans le mode strict, le chemin spécifié doit correspondre exactement à la
structure du document JSON requêté pour renvoyer un élément SQL/JSON, donc
utiliser cette expression de chemin causera une erreur. Pour obtenir le
même résultat que dans le mode permissif, vous devez explicitement
déballer le tableau segments
:
strict $.track.segments[*].location
L'accesseur .**
peut apporter des résultats surprenants
lors de l'utilisation du mode non strict. Par exemple, la requête suivante
sélectionne chaque valeur HR
deux fois :
lax $.**.HR
Ceci survient parce que l'accesseur .**
sélectionne à
la fois le tableau de segments
et chacun de ses
éléments, alors que l'accesseur .HR
déballe
automatiquement les tableaux lors de l'utilisation du mode non strict.
Pour éviter des résultats surprenants, nous recommandons d'utiliser
l'accesseur .**
uniquement dans le mode strict. la
requête suivant sélectionne chaque valeur HR
une seule
fois :
strict $.**.HR
Tableau 9.48 montre les opérateurs et
méthodes disponibles pour jsonpath
. Notez que, bien que les
opérateurs et méthodes unaires puissent être appliqués à de nombreuses
valeurs résultant d'une étape de chemin précédente, les opérateurs
binaires (addition etc.) peuvent seulement être appliqués à des valeurs
seules.
Tableau 9.48. Opérateurs et méthodes jsonpath
Opérateur/Méthode Description Exemple(s) |
---|
Addition
|
Plus unaire (pas d'opération) ; contrairement à l'addition, ceci peut itérer sur plusieurs valeurs
|
Soustraction
|
Négation ; contrairement à la soustraction, ceci peut itérer sur plusieurs valeurs
|
Multiplication
|
Division
|
Modulo (reste)
|
Type de l'élément JSON (voir
|
Taille de l'élément JSON (nombre d'éléments d'un tableau, ou 1 si ce n'est pas un tableau)
|
Nombre flottant approximatif converti en nombre JSON ou en chaîne
|
Entier le plus proche, plus grand ou égal au nombre donné
|
Entier le plus proche, plus petit ou égal au nombre donné
|
Valeur absolue du nombre donné
|
Valeur date/heure convertie en chaîne
|
Valeur date/heure convertie en une chaîne en utilisant le modèle
|
Les paires clé-valeur de l'objet, représentées sous la forme d'un
tableau d'objets contenant trois champs :
|
Le type de résultat des méthodes datetime()
et
datetime(
peut
être template
)date
, timetz
, time
,
timestamptz
ou timestamp
. Les deux méthodes
déterminent dynamiquement le type du résultat.
La méthode datetime()
trie en séquence pour faire
correspondre sa chaîne en entrée aux formats ISO pour les types
date
, timetz
, time
,
timestamptz
et timestamp
. Elle s'arrête au
premier format correspondant et émet le type de données correspondant.
La méthode datetime(
détermine le type de résultat suivant les champs utilisés dans la chaîne
modèle fournie.
template
)
Les méthodes datetime()
et
datetime(
utilisent les mêmes règles d'analyse que la fonction SQL
template
)to_timestamp
(voir Section 9.8), avec trois exceptions. Tout d'abord,
ces méthodes n'autorisent pas les motifs de modèle sans correspondance.
Ensuite, seuls les séparateurs suivants sont autorisés dans la chaîne
modèle : signe moins, point, barre oblique, virgule, apostrophe,
point-virgule, deux-points et espace. Enfin, les séparateurs dans la
chaîne modèle doivent correspondre exactement à la chaîne en entrée.
Si différents types date/heure doivent être comparés, une conversion
implicite est appliquée. Une valeur date
peut être
convertie en timestamp
ou timestamptz
, une
valeur timestamp
peut être convertie en
timestamptz
, et une valeur time
en
timetz
. Néanmoins, toutes sauf la première de ces
conversions dépendent du paramétrage actuel de TimeZone, et de ce fait peuvent seulement être réalisées
à travers les fonctions jsonpath
sensibles au fuseau
horaire.
Tableau 9.49 montre les éléments d'expression de filtre disponibles.
Tableau 9.49. Éléments d'expression de filtre jsonpath
Prédicat/valeur Description Exemple(s) |
---|
Comparaison d'égalité (ceci, et les autres opérateurs de comparaison, fonctionnent sur toutes les valeurs scalaires JSON)
|
Comparaison de non égalité
|
Comparaison inférieur
|
Comparaison inférieur ou égal
|
Comparaison supérieur
|
Comparaison supérieur ou égal
|
Constante JSON
|
Constante JSON
|
Constante JSON
|
AND booléen
|
OR booléen
|
NOT booléen
|
Teste si une condition booléenne est
|
Teste si le premier opérande correspond à l'expression rationnelle
donnée par le deuxième opérande, optionnellement avec les
modifications décrites par une chaîne avec les caractères de
|
Teste si le deuxième opérande est une sous-chaîne initiale du premier opérande.
|
Teste si une expression de chemin correspond à au moins un élément
SQL/JSON. Renvoie
|
Les expressions de chemin SQL/JSON permettent la correspondance de texte
selon une expression rationnelle avec le filtre
like_regex
. Par exemple, la requête de chemin SQL/JSON
suivante correspondrait, sans sensibilité à la casse, à toutes les
chaînes d'un tableau commençant avec une voyelle anglaise :
$[*] ? (@ like_regex "^[aeiou]" flag "i")
La chaîne optionnelle flag
pourrait inclure un ou
plusieurs caractères : i
pour une recherche
insensible à la casse, m
pour autoriser
^
et $
à correspondre aux nouvelles
lignes, s
pour autoriser .
à
correspondre à une nouvelle ligne, et q
pour englober
le motif complet (réduisant le comportement à une simple correspondance
de sous-chaîne).
Le standard SQL/JSON emprunte sa définition d'expressions rationnelles de
l'opérateur LIKE_REGEX
qui, à son tour, utilise le
standard XQuery. PostgreSQL n'accepte pas actuellement l'opérateur
LIKE_REGEX
. De ce fait, le filtre
like_regex
est implémenté en utilisant le moteur
d'expression rationnelle POSIX décrit dans Section 9.7.3. Ceci amène différentes variations
mineures du comportement du standard SQL/JSON, listées dans Section 9.7.3.8. Notez, néanmoins, que les incompatibilités
au niveau des lettres du drapeau décrites ici ne s'appliquent pas à
SQL/JSON, car elles traduisent les lettres drapeau de XQuery pour
correspondre à ce que le moteur POSIX attend.
Gardez en tête que l'argument motif de like_regex
est
une chaîne littérale de chemin JSON, écrite suivant les règles données
dans Section 8.14.7. Ceci signifie en particulier
que tout antislash utilisé dans l'expression rationnelle doit être
doublé. Par exemple, pour établir une correspondance aux valeurs de type
chaîne de caractères du document racine ne contenant que des chiffres :
$.* ? (@ like_regex "^\\d+$")