Nous utilisons des cookies pour vous garantir la meilleure expérience sur notre site. Si vous continuez à utiliser ce dernier, nous considèrerons que vous acceptez l'utilisation des cookies. J'ai compris ! ou En savoir plus !.
banniere

Le portail francophone de la géomatique


Toujours pas inscrit ? Mot de passe oublié ?
Nom d'utilisateur    Mot de passe              Toujours pas inscrit ?   Mot de passe oublié ?

Annonce

Printemps des cartes 2024

#1 Sat 05 December 2020 17:25

AlineC
Membre du bureau
Lieu: AVIGNON
Date d'inscription: 5 Sep 2005
Messages: 2094
Site web

Appeler une API à partir de Postgre/postgis

Bonjour,
J'ai une application de gestion des dossiers de subvention habitat qui a été développée en mode web et propose une api publique :
https://db-app-builder.gitlab.io/docume … s/doc-api/

Je voudrais lier ces données avec notre base postgre/postgis de manière à pouvoir les visualiser dans notre carte géo.
Pour être concret, il s'agit de visualiser les informations des dossiers de subvention LLS en lien avec notre "Atlas LLS", logements locatifs sociaux.
Je ne sais pas du tout comment on "appelle" une API dans postgre/postgis ?
Je voudrais bien quelques liens ? Quelques explications ? Pour comprendre progressivement le sujet. Je ne sais même pas si je formule bien la question ?
Merci

Dernière modification par AlineC (Sat 05 December 2020 18:33)

Hors ligne

 

#2 Sat 05 December 2020 18:01

Nicolas Ribot
Membre
Lieu: Toulouse
Date d'inscription: 9 Sep 2005
Messages: 1536

Re: Appeler une API à partir de Postgre/postgis

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

Hors ligne

 

#3 Sat 05 December 2020 18:09

Nicolas Ribot
Membre
Lieu: Toulouse
Date d'inscription: 9 Sep 2005
Messages: 1536

Re: Appeler une API à partir de Postgre/postgis

Voici un exemple d'appel de la fonction::


Code:

select jsonb_pretty(t)
from geocode_add($$
    select '{1}'::text[] as ids, '6, place du parlement' as voie,  
    'TOulouse' as ville, '31000' as cp
$$) as t;

_________
json_pretty

{
    "cp": "31000",
    "ids": "['1']",
    "voie": "6, place du parlement",
    "ville": "TOulouse",
    "latitude": "43.593901",
    "longitude": "1.44386",
    "result_id": "31555_6544_00006",
    "result_city": "Toulouse",
    "result_name": "Place du Parlement",
    "result_type": "housenumber",
    "result_label": "6 Place du Parlement 31000 Toulouse",
    "result_score": "0.91",
    "result_street": "",
    "result_context": "31, Haute-Garonne, Occitanie",
    "result_oldcity": "",
    "result_citycode": "31555",
    "result_district": "",
    "result_postcode": "31000",
    "result_housenumber": "6",
    "result_oldcitycode": ""
}

-- et pour en faire une geom postgis en 2154 par ex:
select st_astext(
    st_transform(
        st_setSRID(
            st_makePoint((t->>'longitude')::float, (t->>'latitude')::float), 4326),
        2154)
    ) as geom
from geocode_add($$select '{1}'::text[] as ids, '6, place du parlement' as voie,  'TOulouse' as ville, '31000' as cp$$) as t;

_____
geom
POINT(574306.714913341 6278443.54202644)

(dommage, l'API est privée: on ne peut pas tester)

Nico

Hors ligne

 

#4 Sat 05 December 2020 18:21

Nicolas Ribot
Membre
Lieu: Toulouse
Date d'inscription: 9 Sep 2005
Messages: 1536

Re: Appeler une API à partir de Postgre/postgis

Je n'ai pas précisé, mais la création d'une fonction en python nécessite d'installer l'extension plpython3u.

Nico

Hors ligne

 

#5 Sat 05 December 2020 18:25

AlineC
Membre du bureau
Lieu: AVIGNON
Date d'inscription: 5 Sep 2005
Messages: 2094
Site web

Re: Appeler une API à partir de Postgre/postgis

Donc si je traduit dans ma langue de beotienne :
Un connecteur = fdw
Et une requête classique SQL ou équivalent qui appelle les champs souhaités.
C'est ça ?

Dernière modification par AlineC (Sat 05 December 2020 18:25)

Hors ligne

 

#6 Sat 05 December 2020 18:32

AlineC
Membre du bureau
Lieu: AVIGNON
Date d'inscription: 5 Sep 2005
Messages: 2094
Site web

Re: Appeler une API à partir de Postgre/postgis

Je vous avais pas mis le bon lien :
https://db-app-builder.gitlab.io/docume … s/doc-api/
J'ai corrigé aussi dans mon premier message

Dernière modification par AlineC (Sat 05 December 2020 18:34)

Hors ligne

 

#7 Sat 05 December 2020 20:03

Nicolas Ribot
Membre
Lieu: Toulouse
Date d'inscription: 9 Sep 2005
Messages: 1536

Re: Appeler une API à partir de Postgre/postgis

Oui, un FDW est un connecteur vers une source de données étrangère, qui sera vue par PG comme une table normale (lignes et colonnes), donc manipulable également en SQL.

Mais une fonction est aussi une table du point de vue PG: elle renvoie une ou plusieurs lignes, et une ou plusieurs colonnes.

Je ferais d'abord un test avec un langage comme python et une fonction, avant de développer un FDW.

Nicolas

Hors ligne

 

#8 Wed 16 December 2020 19:25

AlineC
Membre du bureau
Lieu: AVIGNON
Date d'inscription: 5 Sep 2005
Messages: 2094
Site web

Re: Appeler une API à partir de Postgre/postgis

Bon,

Pour l'instant je rame encore pour bien comprendre comment ça fonctionne.
C'était tellement simple de se connecter avec tous types de bases de données avec des connexions ODBC ou autres ...
Je sais pas où on met le token ?
Est ce que je peux facilement me connecter via par exemple power bi (je cherche avec les outils que j'ai sous la main).
Mon collègue est arrivé à se connecter à une table mais je croyais qu'avec une API on pouvait aussi "charger" la structure des données ?

Donc, même si j'ai l'air un peu niaise sur le coup, n'hésitez pas à m'apporter quelques compléments d'info, je vais finir pas comprendre !
Merci d'avance

Hors ligne

 

#9 Wed 16 December 2020 20:54

Nicolas Ribot
Membre
Lieu: Toulouse
Date d'inscription: 9 Sep 2005
Messages: 1536

Re: Appeler une API à partir de Postgre/postgis

Bonsoir,

Ce n'est pas beaucoup plus compliqué de se connecter à des webservices. ca dépend un peu des technos utilisées.
Concernant le token a passer dans l'exemple fourni, regarder du coté de la doc de la bibliothèque Python Requests (https://requests.readthedocs.io/en/late … t-sessions), elle sait faire ca en passant les headers qui vont bien dans les param de la connexion au webservice.
La doc de l'API indique comment récupérer un token en se basant sur l'email et le pwd du user.

Je ne sais pas pour Power BI, j'imagine qu'il y a des langages de programmation ou de scripting disponibles ?

API est un terme très générique. rien ne garantit que l'API décrive la structure des données autrement que dans une doc.
C'est cette doc qui dit ce qui est possible ou non avec une API.

Les API standards style WFS déclarent souvent la structure des données.

Nicolas

Hors ligne

 

#10 Sat 19 December 2020 18:47

AlineC
Membre du bureau
Lieu: AVIGNON
Date d'inscription: 5 Sep 2005
Messages: 2094
Site web

Re: Appeler une API à partir de Postgre/postgis

Merci Nicolas,

Donc je comprends qu'il y a API et API !
Qu'il faut regarder la documentation au début plutôt qu'après avoir ramé un moment (on l'a fait l'autre jour et à la fin j'ai vu que le connecteur REST trouvé avait un "sauf" donc ça marchait pas)
On va continuer à faire des tests mais on est sur la bonne voie

A +

Hors ligne

 

Pied de page des forums

Powered by FluxBB