Manipuler les objets d'une couche
Les routes /vmap/layers/{id}/query permettent de lire et d'écrire les objets d'une couche
vMap sans connaître la table sous-jacente : vMap résout la source de données (base, schéma,
table, champ identifiant, SRID) à partir de la définition de la couche, puis applique la
requête.
Méthode |
Route |
Objectif |
|---|---|---|
|
|
lit les objets de la couche |
|
|
crée un objet |
|
|
met à jour un objet |
|
|
supprime un objet |
{id}: identifiant de la couche (layer_id) ;{object_id}: valeur du champ identifiant de l'objet dans la table de la couche.
Ces quatre routes exigent un jeton d'authentification valide et l'un des rôles
vmap_user ou vmap_data_manager.
Avertissement
La création se fait sur la collection (/query), sans {object_id} : l'identifiant de
l'objet créé est retourné dans la réponse. Les routes PUT et DELETE portent au
contraire sur un objet précis.
Attention : l'identifiant n'est attribué par la base que si la colonne le prévoit (séquence ou valeur par défaut). Sur une couche dont le champ identifiant est une donnée métier, il doit être fourni dans le corps de la requête.
Note
Au-delà des droits applicatifs vMap, les opérations restent soumises aux droits PostgreSQL
de l'utilisateur sur la table de la couche. La route
GET /vmap/layers/{id}/rights permet de connaître ces droits.
Format des géométries
Les géométries sont échangées en EWKT dans les deux sens : le SRID précède la géométrie, séparé par un point-virgule.
En WGS 84 (EPSG:4326), les coordonnées sont des degrés, dans l'ordre longitude latitude :
SRID=4326;POINT(2.35 48.85)
En Lambert 93 (EPSG:2154), la projection la plus courante en France métropolitaine, ce même point s'écrit avec des coordonnées en mètres :
SRID=2154;POINT(652301.56 6861302.73)
Un polygone en Lambert 93 suit la même logique :
SRID=2154;POLYGON((652300 6861300, 652400 6861300, 652400 6861400, 652300 6861400, 652300 6861300))
En lecture, la géométrie est retournée par ST_AsEWKT. En écriture, elle est reprojetée
vers le SRID de la colonne (ST_Transform(ST_GeomFromEWKT(...), srid)) et, si le type
déclaré de la couche est MULTIPOLYGON, MULTILINESTRING ou MULTIPOINT, convertie en
géométrie multiple.
Note
Le SRID fourni n'a donc pas besoin de correspondre à celui de la colonne : vMap se charge
de la reprojection. En revanche, il doit être exact, faute de quoi la géométrie est écrite
au mauvais endroit sans qu'aucune erreur ne soit remontée. Le paramètre result_srid
permet, en lecture, de demander la géométrie dans une autre projection que celle de la
colonne.
GET /vmap/layers/{id}/query
Paramètres de la lecture
Paramètre |
Obligatoire |
Description |
|---|---|---|
|
non |
liste des colonnes à retourner, séparées par |
|
non |
filtre JSON, voir Le paramètre |
|
non |
colonne de tri |
|
non |
|
|
non |
nombre maximum de lignes ; par défaut la valeur de la propriété |
|
non |
nombre de lignes ignorées en début de résultat |
|
non |
|
|
non |
|
|
non |
SRID dans lequel reprojeter la géométrie retournée |
|
non |
géométrie EWKT ; ne retourne que les objets qui l'intersectent |
|
non |
tampon appliqué à |
|
non |
|
Note
Une valeur de limit est toujours appliquée : c'est une protection contre les requêtes
trop lourdes. Pour parcourir un volume important, il faut paginer avec limit et offset
en s'appuyant sur total_row_number.
Sur une couche polygonale, intersect_buffer est ramené à 0.
Exemple de lecture
curl -X GET "https://[hostname]/vmap/v2/vmap/layers/42/query" \
-H "Authorization: eyJhbGciOiJ..." \
-G \
--data-urlencode "attributs=id|nom|geom" \
--data-urlencode "limit=100"
Réponse de la lecture
{
"status": 1,
"data": [
{ "id": 1, "nom": "Parcelle A", "geom": "SRID=2154;POLYGON((...))" }
],
"total_row_number": 1,
"list_count": 1
}
POST /vmap/layers/{id}/query
Crée un objet dans la table de la couche.
Corps de la requête (création)
Un objet dont les clés sont les noms des colonnes de la table. Seules les colonnes existantes sont prises en compte ; les autres clés sont ignorées. Le champ identifiant n'a pas à être fourni s'il est auto-généré.
curl -X POST "https://[hostname]/vmap/v2/vmap/layers/42/query" \
-H "Authorization: eyJhbGciOiJ..." \
-H "Content-Type: application/json" \
-d '{
"nom": "Nouvelle parcelle",
"surface": 1250,
"geom": "SRID=4326;POLYGON((2.35 48.85, 2.36 48.85, 2.36 48.86, 2.35 48.85))"
}'
Réponse de la création
{
"status": 1,
"data": {
"id": 128,
"nom": "Nouvelle parcelle",
"surface": 1250,
"geom": "SRID=2154;MULTIPOLYGON((...))"
}
}
L'objet complet tel qu'il a été inséré est retourné (RETURNING *), ce qui permet de
récupérer l'identifiant attribué ainsi que les valeurs calculées par la base
(valeurs par défaut, déclencheurs, géométrie reprojetée).
L'insertion est effectuée dans une transaction : en cas d'échec, aucune ligne n'est créée.
Création avec une image ou un document
Pour joindre un fichier, l'appel doit être envoyé en multipart/form-data, avec une partie
fichier nommée comme la colonne qui doit le recevoir. C'est cette présence dans la
requête qui déclenche le traitement de la colonne comme champ fichier — aucune
configuration particulière de la couche n'est nécessaire.
Pour qu'un fichier soit traité comme une image (redimensionnement et génération d'une
miniature) et non comme un simple document, la colonne doit en plus être listée dans le
paramètre vitis_thumbnail_image_files, un objet JSON transmis dans la même requête.
Soit une couche dont la table comporte une colonne photo :
curl -X POST "https://[hostname]/vmap/v2/vmap/layers/42/query" \
-H "Authorization: eyJhbGciOiJ..." \
-F "nom=Nouvelle parcelle" \
-F "surface=1250" \
-F "geom=SRID=2154;POLYGON((652300 6861300, 652400 6861300, 652400 6861400, 652300 6861400, 652300 6861300))" \
-F "photo=@/chemin/local/vue_aerienne.png" \
-F 'vitis_thumbnail_image_files={"photo": true}'
Réponse :
{
"status": 1,
"data": {
"id": 129,
"nom": "Nouvelle parcelle",
"surface": 1250,
"photo": "https://[hostname]/vmap/v2/vitis/downloads?file=eyJhbGciOiJ...",
"geom": "SRID=2154;MULTIPOLYGON((...))"
}
}
Le fichier est écrit sous
<ws_data_dir>/vmap/layer_entities/{layer_id}/documents/{object_id}/{colonne}/{nom_du_fichier},
et la colonne en base ne stocke que le nom du fichier. La réponse, elle, contient
directement l'URL de téléchargement.
Avertissement
Pour une colonne traitée comme image, l'extension du fichier est réécrite en .jpg (sauf
pour un SVG, conservé tel quel), l'image étant convertie au format JPEG. Un fichier
vue_aerienne.png est
donc stocké sous le nom vue_aerienne.jpg : il ne faut pas se fier au nom transmis pour
reconstruire l'URL, mais utiliser celle retournée par l'API.
Les images sont par ailleurs redimensionnées pour ne pas dépasser 1000 px de large ou de haut, en conservant le ratio.
Note
Les colonnes fichier sont toujours traitées comme multi-fichiers : plusieurs parties
portant le même nom de colonne peuvent être envoyées dans un seul appel. En base, les noms
de fichiers sont alors concaténés avec le séparateur |, et la lecture retourne un tableau
d'URL au lieu d'une seule.
Seule la présence de la clé dans vitis_thumbnail_image_files est testée : la valeur
associée importe peu. Sans ce paramètre, le fichier est conservé tel quel, sans
redimensionnement ni changement d'extension — c'est le comportement voulu pour un document
(PDF, fichier bureautique).
Erreurs de la création
Code HTTP |
Réponse |
Cause |
|---|---|---|
302 |
|
l'insertion a échoué : contrainte violée, identifiant non récupérable, erreur SQL. Les champs |
401 |
|
la base de la couche est inaccessible |
500 |
|
la source de données de la couche n'a pas pu être résolue |
PUT /vmap/layers/{id}/query/{object_id}
Met à jour l'objet identifié par {object_id}.
Corps de la requête (mise à jour)
Le même format que pour POST : un objet dont les clés sont les noms des colonnes. Seules
les colonnes présentes dans le corps sont modifiées.
curl -X PUT "https://[hostname]/vmap/v2/vmap/layers/42/query/128" \
-H "Authorization: eyJhbGciOiJ..." \
-H "Content-Type: application/json" \
-d '{
"nom": "Parcelle renommée",
"surface": 1300
}'
Réponse de la mise à jour
{
"status": 1,
"data": {
"id": 128,
"nom": "Parcelle renommée",
"surface": 1300,
"geom": "SRID=2154;MULTIPOLYGON((...))"
}
}
L'objet retourné est celui obtenu après mise à jour, enrichi le cas échéant des références de fichiers de la couche.
Erreurs de la mise à jour
Code HTTP |
|
Cause |
|---|---|---|
401 |
|
l'objet n'existe pas ou la mise à jour a échoué |
401 |
|
la base de la couche est inaccessible |
500 |
|
la source de données de la couche n'a pas pu être résolue |
DELETE /vmap/layers/{id}/query/{object_id}
Supprime l'objet identifié par {object_id}. Aucun corps de requête n'est attendu.
curl -X DELETE "https://[hostname]/vmap/v2/vmap/layers/42/query/128" \
-H "Authorization: eyJhbGciOiJ..."
Réponse de la suppression
{
"status": 1,
"data": 128
}
L'existence de l'objet est vérifiée avant suppression. Une fois la ligne supprimée, vMap
supprime également le répertoire des documents associés à cet objet
(<ws_data_dir>/vmap/layer_entities/{id}/documents/{object_id}).
Avertissement
La suppression est définitive : ni la ligne, ni les documents et images rattachés à l'objet ne sont récupérables.
Erreurs de la suppression
Code HTTP |
Réponse |
Cause |
|---|---|---|
302 |
|
aucun objet ne correspond à |
401 |
|
la base de la couche est inaccessible |
500 |
|
la source de données de la couche n'a pas pu être résolue |
Variantes multi-objets
Pour agir sur plusieurs objets en un seul appel, trois routes complémentaires existent :
Méthode |
Route |
Description |
Corps |
|---|---|---|---|
|
|
applique les mêmes valeurs à plusieurs objets |
les colonnes à modifier, plus |
|
|
supprime plusieurs objets |
|
|
|
met à jour un objet et en insère d'autres dans la même opération |
|
Note
POST /vmap/layers/{id}/queries est transactionnel au sens applicatif : si une insertion
échoue, les objets déjà insérés sont supprimés et l'objet mis à jour est restauré dans son
état d'origine.
Personnalisation par module
Un module peut fournir son propre contrôleur pour une couche donnée. Si ce contrôleur
redéfinit postQueryLayer, updateQueryLayer, deleteQueryLayer,
multiUpdateQueryLayer ou postAndUpdateQueryLayer, c'est sa version qui est exécutée à
la place du comportement décrit ci-dessus. Ces routes peuvent donc se comporter
différemment sur les couches gérées par un module métier.