Message posté par : Nicolas Ribot
----------------------------------------
Bonsoir,
PG en tant que tel n'est pas outillé pour accéder à des URL, des API.
Mais il supporte de nombreux langages qui permettent ces accès, à travers des fonctions
écrites dans ces langages.
Une solution classique est de développer un serveur d'application (java, javascript,
python, php, ...) qui fait les accès à l'API et le lien vers PG/Pgis pour stocker ou
manipuler les données.
Je préfère souvent une solution intégrée à PG, soit à travers une fonction qui réalise les
accès, soit à travers un FDW (foreign data wrapper). Je vous laisse regarder le FDW
Unicorn, par ex, qui permet en python de développer une interface entre le service et PG,
permettant d'accèder à l'API à travers du sql (select * from
foreign_table_qui_appelle_lapi).
Ca se met en place assez facilement et convient bien si ces appels à l'API doivent
etre nombreux et/ou fréquents.
Il existe aussi des FDW génériques qui savent "taper" sur une API ou un web
service avec un peu de conf.
Avec une fonction, c'est encore plus simple: vous développez la fonction (par ex en
python, langage vraiment pratique pour manipuler les données et disposant de nombreuses
API) qui appelle l'API et traite les données.
Voici un exemple de fonction permettant de géocoder des adresses dans PG. Elle se base sur
le geocodeur en ligne BANO, prend une requete SQL formatée avec certaines colonnes (rue,
num, ville, cp, ...), transmet ces données à l'API du geocodeur, récupère les données
(format CSV), les convertit en JSON et les renvoie à PG.
La concision du code Python pour faire tout cela (ca doit pouvoir etre bien plus concis:
je suis nul en python...) est remarquable je trouve.
(le code execute la requête passée en param, formate le tout en CSV (en mémoire), puis
envoie ce CSV sur l'URL du geocodeur.
Le résultat (CSV) est converti en JSON et renvoyé par la fonction: on peut alors convertir
les info JSON en geométries postgis.)
-----------------
Code :
create or replace function geocode_add(query text)
RETURNS setof jsonb as
$$
import csv
import io
from collections import OrderedDict
import requests
import json
with io.BytesIO(b"") as stream:
writer = csv.writer(stream, delimiter=',', quotechar='"',
quoting=csv.QUOTE_MINIMAL)
writer.writerow(["ids", "voie", "ville",
"cp"])
for row in plpy.cursor(query):
# writes row in csv to csv stream
# Write CSV Header, If you dont need that, remove this line
writer.writerow([row['ids'], row['voie'], row['ville'],
row['cp']])
requests_session = requests.Session()
kwargs = {
'data': OrderedDict([
('columns', ['voie', 'ville', 'cp']),
('postcode', 'cp')
]),
'method': 'post',
'files': OrderedDict([
('data', ('addpg.csv',stream.getvalue()))
]),
'stream': True,
'url': 'https://api-adresse.data.gouv.fr/search/csv/'
}
response = requests_session.request(**kwargs)
for row in csv.DictReader(response.text.encode('utf-8').splitlines()):
yield json.dumps(row)
$$ language plpythonu VOLATILE;
-----------------
Elle s'utilise comme cela:
-----------------
Code :
select * from geocode_add('select array_agg(s.id) as ids, voie, ville, cp from
table_adresse');
-----------------
Nicolas
----------------------------------------
Le message est situé
https://georezo.net/forum/viewtopic.php?pid=337775#p337775
Pour y répondre : geobd(a)ml.georezo.net ou reply de votre messagerie
Pour vous désabonner connectez-vous sur le forum puis Profil / Abonnement
--
Association GeoRezo - le portail géomatique
https://georezo.net