NOTE: Vous avez la possibilité d’utiliser ce GitHub Codespaces pour pratiquer avec Redis https://github.com/voirinprof/gis_starter_redis_geolab, MongoDb https://github.com/voirinprof/gis_starter_mongodb_geolab ou Neo4j https://github.com/voirinprof/gis_starter_neo4j_geolab. Pour mettre en place un environnement Codespaces allez voir Premiers pas avec GitHub Codespaces.

Introduction aux bases de données NoSQL

Les bases de données NoSQL (Not Only SQL) sont conçues pour gérer des données non structurées, semi-structurées ou structurées. Contrairement aux bases relationnelles comme PostgreSQL, elles n’utilisent pas de schémas rigides et privilégient la performance pour des volumes de données importants ou des structures variées. Ce guide introduit trois bases NoSQL populaires : Redis, MongoDB et Neo4j, avec un focus sur leur utilisation pour des données spatiales.

Présentation de Redis, MongoDB et Neo4j

  • Redis : Une base de données en mémoire de type clé-valeur, optimisée pour la rapidité. Elle est idéale pour le caching, les sessions utilisateur, ou les index spatiaux simples grâce à ses commandes géospatiales.
  • MongoDB : Une base de données orientée documents, stockant des données sous forme de documents JSON/BSON. Elle prend en charge les index géospatiaux pour les requêtes de proximité ou d’intersection.
  • Neo4j : Une base de données orientée graphes, conçue pour modéliser des relations complexes, y compris des réseaux spatiaux (par exemple, routes ou infrastructures). Les données sont stockées sous forme de nœuds et d’arêtes.

Redis

Configuration

Redis est léger et rapide. Pour démarrer, installez Redis localement ou utilisez un service cloud comme Redis Labs.

Commande pour démarrer un serveur Redis local (après installation) :

redis-server

Connexion via le client CLI :

redis-cli

Conseil : Vérifiez que Redis est installé (redis-server --version) avant de lancer le serveur.

Création et insertion de données

Redis stocke des paires clé-valeur et prend en charge les données géospatiales via des commandes comme GEOADD. Exemple d’insertion d’un point d’intérêt (par exemple, la Tour Eiffel) :

GEOADD lieux 2.2945 48.8584 "Tour Eiffel"
  • GEOADD : Ajoute une position (longitude, latitude, nom) à une clé de type ensemble géospatial.

Exemple avec plusieurs points :

GEOADD lieux 4.8357 45.7640 "Lyon" 5.3698 43.2965 "Marseille"

Conseil : Les clés géospatiales Redis sont idéales pour des recherches rapides de proximité.

Requêtes de base et spatiales

Récupérer une clé :

GET utilisateur:123

Obtenir tous les éléments d’une liste :

LRANGE taches 0 -1

Supprimer une clé :

DEL utilisateur:123

Trouver des lieux dans un rayon de 100 km autour de la Tour Eiffel :

GEORADIUS lieux 2.2945 48.8584 100 km

Calculer la distance entre deux lieux :

GEODIST lieux "Tour Eiffel" "Lyon" km

Conseil : Les commandes GEORADIUS et GEORADIUSBYMEMBER sont rapides mais limitées aux calculs sphériques simples.

Optimisation des performances

  • Utilisez des structures adaptées : Les ensembles géospatiaux (GEOADD) sont optimisés pour les recherches de proximité.
  • Définissez des expirations : Pour les données temporaires (par exemple, cache géospatial), utilisez EXPIRE :
    SETEX cache:lieux:paris "donnees" 3600  # Expire après 1 heure
    

MongoDB

Configuration

MongoDB peut être installé localement ou utilisé via MongoDB Atlas (cloud). Pour une installation locale, téléchargez MongoDB Community Server.

Démarrer le serveur MongoDB :

mongod

Connexion via le client MongoDB Shell :

mongo

Créer une base de données :

use ma_base_de_donnees

Conseil : MongoDB crée automatiquement la base lors de la première insertion si elle n’existe pas.

Création et insertion de données

MongoDB organise les données en collections de documents et prend en charge les coordonnées géospatiales via le type GeoJSON. Exemple d’insertion dans une collection points_interet :

db.points_interet.insertOne({
    nom: "Tour Eiffel",
    location: {
        type: "Point",
        coordinates: [2.2945, 48.8584]  // [longitude, latitude]
    }
})

Insérer plusieurs points :

db.points_interet.insertMany([
    { nom: "Lyon", location: { type: "Point", coordinates: [4.8357, 45.7640] } },
    { nom: "Marseille", location: { type: "Point", coordinates: [5.3698, 43.2965] } }
])

Conseil : Assurez-vous que le champ location suit le format GeoJSON pour les requêtes spatiales.

Requêtes de base et spatiales

Sélectionner tous les documents d’une collection :

db.points_interet.find().pretty()

Filtrer par critère :

db.points_interet.find({ nom: "Tour Eiffel" }).pretty()

Mettre à jour un document :

db.points_interet.updateOne(
    { nom: "Tour Eiffel" },
    { $set: { nom: "Tour Eiffel - Paris" } }
)

Supprimer un document :

db.points_interet.deleteOne({ nom: "Tour Eiffel" })

Créer un index géospatial :

db.points_interet.createIndex({ location: "2dsphere" })

Trouver les points dans un rayon de 100 km autour de la Tour Eiffel :

db.points_interet.find({
    location: {
        $near: {
            $geometry: { type: "Point", coordinates: [2.2945, 48.8584] },
            $maxDistance: 100000  // 100 km en mètres
        }
    }
}).pretty()

Vérifier si un point est dans un polygone :

db.points_interet.find({
    location: {
        $geoWithin: {
            $geometry: {
                type: "Polygon",
                coordinates: [[
                    [2.2, 48.8], [2.4, 48.8], [2.4, 48.9], [2.2, 48.9], [2.2, 48.8]
                ]]
            }
        }
    }
}).pretty()

Conseil : Utilisez $near pour les recherches de proximité et $geoWithin pour les intersections.

Optimisation des performances

  • Créez des index géospatiaux : L’index 2dsphere est essentiel pour les requêtes $near et $geoWithin :
    db.points_interet.createIndex({ location: "2dsphere" })
    
  • Limitez les champs : Récupérez uniquement les champs nécessaires pour réduire la charge :
    db.points_interet.find({ nom: "Tour Eiffel" }, { nom: 1, location: 1, _id: 0 })
    

Neo4j

Configuration

Neo4j propose une version desktop (Neo4j Desktop) ou serveur. Téléchargez Neo4j Community Edition pour commencer.

Démarrer Neo4j (après installation) :

  1. Lancez Neo4j Desktop ou exécutez neo4j start pour un serveur local.
  2. Accédez à l’interface web (par défaut : http://localhost:7474).
  3. Connectez-vous avec les identifiants par défaut (souvent neo4j/neo4j) et changez le mot de passe.

Conseil : Familiarisez-vous avec le langage Cypher pour interroger Neo4j, en particulier pour les requêtes spatiales.

Vidéo utile : Introduction aux bases de données NoSQL

Création et insertion de données

Neo4j utilise le langage Cypher pour créer des nœuds et des relations. Pour les données spatiales, Neo4j prend en charge le type Point (depuis la version 3.4). Exemple de création d’un lieu et d’une relation :

CREATE (tour:PointInteret {nom: "Tour Eiffel", location: point({longitude: 2.2945, latitude: 48.8584, srid: 4326})})
CREATE (lyon:PointInteret {nom: "Lyon", location: point({longitude: 4.8357, latitude: 45.7640, srid: 4326})})
CREATE (tour)-[:PROCHE]->(lyon)
  • point : Type spatial pour stocker des coordonnées.
  • srid: 4326 : Système de référence WGS84.

Conseil : Utilisez des relations comme PROCHE pour modéliser des réseaux spatiaux.

Vidéo utile : Premiers pas avec MongoDB (en anglais)

Requêtes de base et spatiales

Trouver tous les nœuds avec l’étiquette PointInteret :

MATCH (p:PointInteret)
RETURN p

Trouver les lieux reliés à la Tour Eiffel :

MATCH (tour:PointInteret {nom: "Tour Eiffel"})-[:PROCHE]->(lieu)
RETURN lieu.nom

Supprimer un nœud et ses relations :

MATCH (p:PointInteret {nom: "Tour Eiffel"})
DETACH DELETE p

Trouver les lieux dans un rayon de 100 km autour de la Tour Eiffel :

WITH point({longitude: 2.2945, latitude: 48.8584, srid: 4326}) AS centre
MATCH (p:PointInteret)
WHERE distance(p.location, centre) < 100000  // 100 km en mètres
RETURN p.nom, distance(p.location, centre) / 1000 AS distance_km

Créer une relation basée sur la proximité (moins de 200 km) :

MATCH (p1:PointInteret), (p2:PointInteret)
WHERE p1.nom < p2.nom AND distance(p1.location, p2.location) < 200000
CREATE (p1)-[:PROCHE {distance_km: distance(p1.location, p2.location) / 1000}]->(p2)
RETURN p1.nom, p2.nom

Conseil : La fonction distance utilise des calculs sphériques pour les points WGS84.

Vidéo utile : Introduction à Neo4j et Cypher (en anglais)

Optimisation des performances

  • Indexez les propriétés clés : Accélérez les recherches sur les propriétés comme nom :
    CREATE INDEX FOR (p:PointInteret) ON (p.nom)
    
  • Utilisez des index spatiaux : Depuis Neo4j 4.0, les index spatiaux accélèrent les requêtes sur point :
    CREATE POINT INDEX FOR (p:PointInteret) ON (p.location)
    
  • Optimisez les motifs : Limitez les nœuds parcourus dans les requêtes spatiales avec des conditions précises.

Conseil : Testez les performances avec des volumes de données réalistes pour identifier les goulots d’étranglement.

Bonnes pratiques

  • Choisissez le bon outil : Redis pour des recherches géospatiales rapides (proximité), MongoDB pour des documents géospatiaux flexibles, et Neo4j pour des réseaux spatiaux complexes.
  • Validez les données : Vérifiez les formats (GeoJSON pour MongoDB, point pour Neo4j) avant insertion.
  • Testez les requêtes spatiales : Utilisez des coordonnées réelles (par exemple, villes françaises) pour valider les résultats.
  • Sauvegardez régulièrement : Configurez des sauvegardes automatiques, surtout pour MongoDB et Neo4j.
  • Surveillez les performances : Utilisez Redis Monitor, MongoDB Compass, ou Neo4j Browser pour analyser l’activité.

Exemple de contrainte dans Neo4j pour garantir l’unicité des noms :

CREATE CONSTRAINT FOR (p:PointInteret) REQUIRE p.nom IS UNIQUE

Vidéo utile : Redis pour les débutants (en anglais)