J'essaie la requête suivante:
SELECT (json_data->'position'->'lat') + 1.0 AS lat FROM updates LIMIT 5;
(Le +1.0 est juste là pour forcer la conversion à flotter. Mes requêtes réelles sont beaucoup plus complexes, cette requête n'est qu'un test pour le problème.)
Je reçois l'erreur:
ERROR: operator does not exist: jsonb + numeric
Si j'ajoute un casting explicite:
SELECT (json_data->'position'->'lat')::float + 1.0 AS lat FROM updates LIMIT 5;
l'erreur devient:
ERROR: operator does not exist: jsonb + double precesion
Je comprends que la plupart des valeurs jsonb ne peuvent pas être converties en flottants, mais dans ce cas, je sais que les lats sont tous des nombres JSON.
Existe-t-il une fonction qui convertit les valeurs jsonb en flottants (ou renvoie des valeurs NULL pour les non-castables)?
Il y a deux opérations pour obtenir la valeur de JSON
. Le premier ->
renverra JSON
. Le deuxième ->>
renverra du texte.
Détails: Fonctions et opérateurs JSON
Essayer
SELECT (json_data->'position'->>'lat')::float + 1.0 AS lat
FROM updates
LIMIT 5
Par documentation , il y a aussi les fonctions
jsonb_populate_record()
jsonb_populate_recordset()
Analogique à leurs jumeaux Json (présents depuis la page 9.3)
json_populate_record()
json_populate_recordset()
Vous avez besoin d'un type de ligne prédéfini. Utilisez le type de ligne d'une table existante ou définissez-en un avec CREATE TYPE
. Ou remplacez par une table temporaire ad hoc:
CREATE TEMP TABLE x(lat float);
Peut être une seule colonne ou une longue liste de colonnes.
Seules ces colonnes sont remplies, où le nom correspond à une clé dans le json
objet. La valeur est contrainte au type de colonne et doit être compatible ou une exception est levée. Les autres clés sont ignorées.
SELECT lat + 1 -- no need for 1.0, this is float already
FROM updates u
, jsonb_populate_record(NULL::x, u.json_data->'position')
LIMIT 5;
Utiliser un implicite LATERAL JOIN
ici.
De même, utilisez jsonb_populate_recordset()
pour décomposer les tableaux en plusieurs lignes par entrée.
Cela fonctionne de la même manière dans Postgres 9.3 avec json
. Il y a l'avantage supplémentaire que la conversion vers/depuis text
en interne n'est pas nécessaire pour les données numériques dans jsonb
.
AFAIK il n'y a pas de casting json-> float dans Postgres, vous pouvez donc essayer un cast explicite (json_data->'position'->'lat')::text::float
Ajout d'une clarification car cela apparaît comme le résultat le plus recherché pour une recherche de `` conversion flottante JSONB '' - notez que vous devez encapsuler la conversion JSON entre crochets, et alors appliquer le casting '::'.
Comme mentionné ci-dessus, la bonne méthode est:
(json_data #>> '{field}')::float
Si vous essayez à la place, cela échouera:
json_data #>> '{field}'::float
C'était l'erreur que je faisais dans mon code et il m'a fallu un certain temps pour le voir - solution facile une fois que j'ai remarqué.
Vous devez transtyper la valeur json en texte puis flotter.
Essaye ça:
(json_data #>> '{field}')::float