4.7. Utilisation de Mapserver


Minnesota Mapserver est un serveur cartographique Internet qui se conforme aux spécifications "Web Mapping Server" de l'OpenGIS.

 Table des matières

4.7.1. Utilisation de base
4.7.2. Questions fréquemment posées
4.7.2.1. Lorsque j'utilise une EXPRESSION dans ma map, la condition ne retourne jamais vrai, même si elle devrait.
4.7.2.2. Le FILTER que j'utilise pour mon fichier vecteur ne fonctionne pas pour ma table PostGIS contenant les mêmes données.
4.7.2.3. Ma couche PostGIS se dessine plus doucement que mon fichier vecteur, est-ce normal?
4.7.2.4. Mes couches PostGIS s'affichent correctement, mais les requêtes sont vraiment lentes. Que se passe-t-il ?
4.7.3. Utilisation avancée
4.7.4. Exemples

4.7.1. Utilisation de base

Pour utiliser PostGIS avec Mapserver vous aurez besoin de savoir comment configurer Mapserver, ce qui dépasse le cadre de cete documentation. Cette section va couvrir les particularités d'une utilisation avec Postgis et les détails de la configuration.

Pour utiliser PostGIS avec Mapserver, vous aurez besoin de :

Mapserver accède aux données PostgreSQL/PostGIS comme n'importe quel autre client PostgreSQL - c'est à dire en utilisant la libpq. Cela signifie que Mapserver peut être installé sur chaque machines ayant un accès réseau vers un serveur PostGIS, temps que le système possède la libraire client de PostgreSQL (libpq).

  1. Compilez et installez Mapserver, avec les supports qui vous souhaitez activer, incluant l'option de configuration : "--with-postgis".
  2. Dans votre fichier map de Mpaserver, ajouté une couche PostGIS. Par exemple :
    LAYER
      CONNECTIONTYPE postgis
      NAME "widehighways"
      # Connect to a remote spatial database
      CONNECTION "user=dbuser dbname=gisdatabase host=bigserver"
      # Get the lines from the 'geom' column of the 'roads' table
      DATA "geom from roads"
      STATUS ON
      TYPE LINE
      # Of the lines in the extents, only render the wide highways
      FILTER "type = 'highway' and numlanes >= 4"
      CLASS
        # Make the superhighways brighter and 2 pixels wide
        EXPRESSION ([numlanes] >= 6)
        COLOR 255 22 22
        SYMBOL "solid"
        SIZE 2
      END
      CLASS
        # All the rest are darker and only 1 pixel wide
        EXPRESSION ([numlanes] < 6)
        COLOR 205 92 82
      END
    END

    Dans l'exemple ci-dessus, les directives spécifiques à PostGIS sont les suivantes :

    CONNECTIONTYPE
    Pour les couches PostGIS, cela sera toujours "postgis".

    CONNECTION
    La connection à la base de données est gouvernée par "la chaine de charatères de connection" ("connection string") qui est contituée d'un ensemble de couples nom/valeur comme ceci (avec la valeur par défaut entre < >) :
    user=<nom_d_utilisateur> password=<mot_de_passe> dbname=<nom_de_la_base_de_données> hostname=<serveur> port=<5432>
    Une chaine de charactères de connection vide reste valide, et chacun des couples nom/valeur peut être omis. Au minimum vous aurez généralement besoin de spécifier le nom de la base de données et le nom d'utilisateur avec lequel vous souhaitez vous connecter.

    DATA
    La forme de ce paramètre est : "<colonne> from <nom_de_la_table>" où la colonne est une colonne spatiale qui doit être affiché sur la carte.

    FILTER
    Le filtre doit être une chaîne de charactères SQL valide correspondant à la logique normale suivant le mot clef "WHERE" dans les requêtes SQL. Donc, par exemple, pour afficher uniquement les routes ayant 6 voies ou plus, utilisé le filtre "nombre_de_voies >= 6".

  3. Dans votre base de données spatiale, assurez vous que vous avez des indexes spatiaux (GiST) pour chaque couches que vous souhaitez afficher.
    CREATE INDEX [nom_de_l_index]
    ON [nom_de_la_table]
    USING GIST ( [colonne_géometrique] GIST_GEOMETRY_OPS );
  4. Si vous allez interroger vos couches en utilisant Mpaserver vous aurez aussi besoin d'un "index oid".
    Mapserver requière des indentifiants uniques pour chaque enregistrement spatial lorsque vous souhaitez effetuer des interrogations, et le module PostGIS de Mapserver utilise les valeurs d'oid de PostgreSQL pour fournir ces identifiants uniques. Cela implique comme effet de bord que si vous souhaitez effectuer des accès aléatoires rapides aux enregistrements durant les requêtes, un index sur les oid est necessaires.
    Pour construire un tel index, utilisez la requête SQL suivante :
    CREATE INDEX [nom_de_l_index] ON [nom_de_la_table] ( oid );

haut de la page | table des matières

4.7.2. Questions fréquemment posées


haut de la page | table des matières

4.7.2.1. Lorsque j'utilise une EXPRESSION dans ma map, la condition ne retourne jamais vrai, même si elle devrait.

Contrairement aux fichiers vecteurs (shapefile), les noms de champs PostGIS doivent être référencés dans EXPRESSIONS en utilisant des lettres en minuscule.

EXPRESSION ([nombre_de_voies] >= 6)
haut de la page | table des matières

4.7.2.2. Le FILTER que j'utilise pour mon fichier vecteur ne fonctionne pas pour ma table PostGIS contenant les mêmes données.

Contrairement aux fichiers vecteurs (shapefile), les filtres pour les couches PostGIS utilisent la syntaxe SQL (ils sont concaténés à l'état SQL que le connecteur PostGIS génère pour afficher les couches dans Mapserver).

FILTER "type = 'autoroute' and nombre_de_voies >= 4"
haut de la page | table des matières

4.7.2.3. Ma couche PostGIS se dessine plus doucement que mon fichier vecteur, est-ce normal?

En général, les couches PostGIS sont 10 % plus lentes que les couches équivalentes en fichier vecteurs, ceci est due au temps qui incombe à la connection au serveur de base de données, les transformations et la transmission des données entre la base et Mapserver.

Si vous avez des problèmes de performance d'affichage, cela est généralement lié au fait que vous n'avez pas créé les indexes spatiaux pour vos tables.

postgis# CREATE INDEX geotable_gix ON geotable USING GIST ( geocolumn );
postgis# SELECT update_geometry_stats(); -- Pour PGSQL < 8.0
postgis# VACUUM ANALYZE; -- Pour PGSQL >= 8.0
haut de la page | table des matières

4.7.2.4. Mes couches PostGIS s'affichent correctement, mais les requêtes sont vraiment lentes. Que se passe-t-il ?

Pour que les requêtes soient rapides, vous devez avoir une clef unique pour vos tables spatiales et un index sur cette clef unique.
Vous pouvez spécifier quelle clef unique doit être utilisée par Mapserver, en utilisant la clause : USING UNIQUE dans votre ligne DATA :
DATA "the_geom FROM geotable USING UNIQUE gid"
Si votre table n'a pas de colonne explicitement unique, vous pouvez "faire semblant" de rendre une colonne unique en utilisant la colonne PostgreSQL "oid" comme colonne unique. "oid" est la colonne unique par défaut si vous n'en déclarez pas une, donc pour améliorer le temps d'exécution de vos requêtes vous devez créer des indexes sur les valeurs oid de vos tables spatiales.
postgis# CREATE INDEX geotable_oid_idx ON geotable (oid);

haut de la page | table des matières

4.7.3. Utilisation avancée

La clause pseudo-SQL USING est utilisée afin d'ajouter des informations pour aider Mapserver à comprendre les résultats de plusieurs requêtes complexes. Plus précisément, lorsqu'une vue ou une sous-requête de sélection est utilisée comme table source (le terme à la droite du FROM dans la définition de DATA) il est plus difficile pour Mapserver de déterminer automatiquement un identifiant unique pour chaque tuple et le SRID pour la table. La clause USING peut fournir à Mapserver ces deux types d'informations :

DATA "the_geom FROM (SELECT table1.the_geom AS the_geom, table1.oid AS oid, table2.data AS data
FROM table1 LEFT JOIN table2 ON table1.id = table2.id) AS new_table USING UNIQUE oid USING SRID=-1"

USING UNIQUE <idunique>

Mapserver requière un identifiant unique pour chaque tuple dans le but d'identifier une ligne lorsque l'on effectue des interrogations de la carte. Normalement, il devrait utiliser l'oid comme identifiant unique, mais les vues et les sous-requêtes de sélection n'ont pas obligatoirement cette colonne oid. Si vous souhaitez utiliser les fonctionnalités d'interrogation de Mapserver, vous aurez besoin d'ajouter une colonne unique à vos vues ou vos sous-requêtes de sélection, et déclarer ceci en utilisant : USING UNIQUE. Pour ce faire, vous pouvez, par exemple, explicitement sélectionner une des valeurs d'oid de la table, ou l'une des autres colonnes pour laquelle vous garantissez l'unicité dans l'ensemble résultant.

L'état USING peut aussi être utile pour de simples état DATA, si vous effectuez des interrogations de la carte. Il était jadis recommandé d'ajouter un indexe sur la colonne oid des tables utilisées dans les couches interrogeables, dans le but d'accélérer les requêtes de la carte. Cependant, avec la clause USING, il est possible de spécifier à Mapserver d'utiliser la clef primaire de votre table comme identifiant pour interroger la carte, il n'est ainsi plus nécessaire d'avoir un indexe supplémentaire.

Note :
"Interroger une carte" est l'action qui consiste à cliquer sur la carte pour demander les informations relatives à la zone géographique sélectionnée. Ne confondez pas "interrogation de carte" avec requête SQL dans la définition de DATA.

USING SRID=<srid>

PostGIS a besoin de connaitre quel système de référence spatial doit être utilisé par les géométries afin de retourner correctement les données à Mapserver. Normalement il est possible de trouver ces informations dans la table "geometry_columns" dans une base de données PostGIS, cependant, il n'est pas possible pour les tables qui ont été créées à la volée comme des sous-requêtes de sélection ou des vues. Donc l'option USING SRID= vous permet de spécifier le SRID correspondant à vos données dans la définition de DATA.

Attention :
Le parser pour les couches PostGIS de Mapserver est légérement primitif et est sensible à la casse dans certaines parties. Faites attention à ce que tous les mots clefs SQL et toutes les clauses USING soient en lettres majuscules, et que vos clauses USING UNIQUE précèdent bien vos clauses USING SRID.

haut de la page | table des matières

4.7.4. Exemples

Commençons avec un exemple simple et qui nous servira de base pour la suite. Considérons la définition de couche Mapserver suivante :

LAYER
 CONNECTIONTYPE postgis
 NAME "routes"
 CONNECTION "user=lutilisateur password=lemotdepasse dbname=labase host=leserveur"
 DATA "the_geom FROM routes"
 STATUS ON
 TYPE LINE
 CLASS
  COLOR 0 0 0
 END
END

Cette couche affichera toutes les géométries de la table routes comme des lignes noires.

Maintenant, supposons que nous voulions uniquement afficher les autoroutes lorsque nous zoomons au moins à une échelle de 1:100000, les deux prochaines couches permettent cela :

LAYER
 CONNECTION "user=lutilisation password=lemotdepasse dbname=labase host=leserveur"
 DATA "the_geom FROM routes"
 MINSCALE 100000
 STATUS ON
 TYPE LINE
 FILTER "type_de_route = 'autotourte'"
 CLASS
  COLOR 0 0 0
 END
END
LAYER
 CONNECTION "user=lutilisateur password=lemotdepasse dbname=labase host=leserveur"
 DATA "the_geom FROM routes"
 MAXSCALE 100000
 STATUS ON
 TYPE LINE
 CLASSITEM type_de_route
 CLASS
  EXPRESSION "autoroute"
  SIZE 2
  COLOR 255 0 0
 END
 CLASS
  COLOR 0 0 0
 END
END

La première couche est utilisée lorsque l'échelle est plus grande que 1:100000, et affiche uniquement des lignes noires pour les routes de type "autoroute". L'option FILTER entraine que seules les routes de type "autoroute" doivent être affichées.

La seconde couche est utilisée lorsque l'échelle est plus petite que 1:100000, et affichera les autoroutes comme des lignes rouges à double-profondeurs, et les autre routes comme des lignes noires standards.

Donc, nous avons fait un couple de choses intéressantes en utilisant uniquement les fonctionnalités de Mapserver, mais nos états SQL dans les définitions de DATA sont restées simples. Supposons que le nom des routes soit stocké dans une autre table (pour une raison quelconque) et que nous souhaitions faire une jointure pour récupérer et étiqueter nos routes.

LAYER
 CONNECTION "user=lutilisateur password=lemotdepasse dbname=labase host=leserveur"
 DATA "the_geom FROM (SELECT routes.oid AS oid, routes.the_geom AS the_geom, nom_des_routes.nom as nom
  FROM routes LEFT JOIN nom_des_routes ON routes.id_nom_de_routes = nom_des_routes.id_nom_de_routes) AS routes_nommées
  USING UNIQUE oid USING SRID=-1"
 MAXSCALE 20000
 STATUS ON
 TYPE ANNOTATION
 LABELITEM nom
 CLASS
  LABEL
   ANGLE auto
   SIZE 8
   COLOR 0 192 0
   TYPE truetype
   FONT arial
  END
 END
END

Cette couche d'annotation ajoute des étiquettes vertes à toutes les routes lorsque l'échelle atteint 1:20000 ou moins. Cela montre aussi comment utiliser les jointures SQL dans une définition de DATA.

haut de la page | table des matières