DéveloppeurWeb.Com
    DéveloppeurWeb.Com
    • Agile Zone
    • AI Zone
    • Cloud Zone
    • Database Zone
    • DevOps Zone
    • Integration Zone
    • Web Dev Zone
    DéveloppeurWeb.Com
    Home»Database Zone»Requêtes géospatiales avec la base de données Oracle JSON
    Database Zone

    Requêtes géospatiales avec la base de données Oracle JSON

    novembre 29, 2022
    Requêtes géospatiales avec la base de données Oracle JSON
    Share
    Facebook Twitter Pinterest Reddit WhatsApp Email

    Dans cet article, je souhaite documenter comment écrire des requêtes géospatiales sur la base de données autonome Oracle. Cet exemple utilisera le module complémentaire node-oracledb pour Node.js et s’exécutera sur une base de données Oracle JSON. Je ne parlerai pas de l’approvisionnement d’une base de données JSON sur Oracle Cloud – cela sera laissé comme exercice à l’utilisateur, s’il le souhaite. Ce premier élément concerne la configuration de l’environnement de développement, la création du projet Node.JS et l’installation de la configuration et des logiciels de prise en charge requis pour se connecter à la base de données distante.

    J’étudiais cette fonctionnalité lors de la création d’une application téléphonique simple qui afficherait les lieux d’intérêt en fonction des coordonnées actuelles de l’utilisateur. J’ai créé une petite application Node.js côté serveur qui s’exécutait dans un cluster Kubernetes frappant une base de données Oracle JSON. Le code présenté ici est une simplification qui illustre simplement l’utilisation de l’API. Dans l’application, l’utilisateur sélectionnerait la distance par rapport à sa position actuelle pour voir tous les lieux d’intérêt à proximité. Ce qui est bien dans cet exemple, c’est que le code est entièrement du côté du développeur (Visual Studio sur Mac) accédant à la base de données distante. Cela facilite le débogage et l’itération.

    L’environnement de développement

    Tout d’abord, provisionnez une base de données JSON sur Oracle Cloud. Essayez-le sur Oracle Free Tier :

    Tableau de bord de l'offre gratuite d'Oracle

    Ensuite, créez un nouveau projet Node.js.

    Installez les bibliothèques de base de données Oracle du nœud.

    Je l’exécute à l’aide de Visual Code sur macOS et je me connecte à ma base de données JSON distante, il y a donc 2 éléments supplémentaires nécessaires pour se connecter : un portefeuille Oracle pour des connexions sécurisées et un client instantané Oracle pour macOS.

    Téléchargez le portefeuille pour votre base de données Oracle JSON. Notez le nom TNS qui sera également nécessaire pour construire le client Oracle.
    Télécharger les informations d'identification du client

    IMPORTANT: Vous devrez mettre à jour sqlnet.ora pour pointer vers l’emplacement du portefeuille. Modifiez sqlnet.ora dans le dossier du portefeuille et mettez à jour :

    WALLET_LOCATION = (SOURCE = (METHOD = file) (METHOD_DATA = (DIRECTORY="/Users/myuser/myProject/wallet")))
    SSL_SERVER_DN_MATCH=yes

    Téléchargez le client instantané pour votre plateforme de développement ; dans ce cas, macOS.

    La structure de répertoires de votre projet devrait ressembler à ceci :

    user@user-mac myProject % ls
    TestIt.js		
    instantclient_19_8	
    node_modules		
    package-lock.json	
    package.json		
    wallet

    Le code

    Que sont les requêtes GeoSpatial ? Ce sont des requêtes sur un ensemble de types de données GeoJSON (Points, Polygonsetc.).

    Oracle fournit un ensemble d’opérateurs QBE ($near, $within et $intersects) qui peut trouver un ensemble d’emplacements en fonction des paramètres de requête. La spécification GeoJSON spécifie un point comme [longitude, latitude]. Peut-être que quelqu’un peut m’expliquer cela, car j’ai toujours pensé que les emplacements étaient donnés en « latitude, longitude », alors gardez cela à l’esprit lors du stockage des points GeoJSON.

    Pourquoi [longitude, latitude]? Il correspond à un système de coordonnées cartésien, [x,y]. C’est la théorie. Alors, où est passé [latitude, longitude] origine ? J’ai demandé sur internet et j’ai trouvé ceci :

    Je ne suis pas un expert dans ce domaine, mais j’ai fait quelques lectures sur le sujet, notamment sur son histoire. Je pense que la raison en est que la mesure précise de la latitude est venue en premier car elle était basée sur des mesures astronomiques. La longitude n’était pas mesurable avec précision jusqu’à ce qu’un appareil de mesure du temps très précis ait été développé.

    Regardons le code. Tout d’abord, importez le oracledb forfait. Cet exemple définit autoCommit à true.

    const oracledb = require('oracledb');
    oracledb.autoCommit = true;

    Initialiser le OracleClient en passant dans l’emplacement du wallet et de l’instant client :

        oracledb.initOracleClient({
          libDir: "/Users/myuser/myProject/instantclient_19_8",
          configDir: "/Users/myuser/myProject/wallet"      
        });

    Connectez-vous maintenant à la base de données. Le TNSNAME est extrait de la même page où le portefeuille a été téléchargé.

    async function connect() {
      await oracledb.createPool({
        user: 'admin',
        password: 'password',
        connectString: 'tnsName',
    })
    .then(pool => this._connectionPool = pool)
    
    return this._connectionPool
    }

    Une fois connecté, créez une nouvelle Collection.

        const myConnectionPool = await connect();
        const myConnection = await myConnectionPool.getConnection();
        const mySodaDB = myConnection.getSodaDatabase();
        const myCollection = await mySodaDB.createCollection('GeoJsonExample');

    Chargez des points GeoJSON avec une longitude décroissante et une latitude croissante :

        // Load up some locations
        for (let i = 0; i < 10; i++) {
          latitude = 30 + (i*.1);
          longitude = 30 - (i*.1);
          let myContent = {
            "location": {
                "type": "Point",
                "coordinates": [
                    longitude,
                    latitude
                ]
            }
          };
          await myCollection.insertOne(myContent);
        } 
    

    Les points de la collection sont les suivants :

    Inital Load of GeoJson Points
    {"location":{"type":"Point","coordinates":[29.8,30.2]}}
    {"location":{"type":"Point","coordinates":[29.7,30.3]}}
    {"location":{"type":"Point","coordinates":[29.6,30.4]}}
    {"location":{"type":"Point","coordinates":[29.5,30.5]}}
    {"location":{"type":"Point","coordinates":[29.4,30.6]}}
    {"location":{"type":"Point","coordinates":[29.3,30.7]}}
    {"location":{"type":"Point","coordinates":[29.2,30.8]}}
    {"location":{"type":"Point","coordinates":[29.1,30.9]}}
    {"location":{"type":"Point","coordinates":[30,30]}}
    {"location":{"type":"Point","coordinates":[29.9,30.1]}}

    Maintenant que nous avons des points, trouvez des points proches d’un point spécifique (dans ce cas, 60 miles) et enregistrez-les. Chacun des opérateurs spatiaux QBE est suivi d’un objet JSON dont les champs doivent inclure $geometry. Opérateur $near doit également inclure le champ $distanceet il peut inclure $unit. Une erreur de compilation est déclenchée si $geometry est manquant ou si $distance ou $unit est présent avec l’opérateur $intersects ou $within(source : documentation Oracle).

        // Find all within a mile
        documents = await myCollection.find().filter({"location":{"$near":{"$geometry":{"type":"Point","coordinates":[30,30]},"$distance":60,"$unit":"mile"}}}).getDocuments();
        contentOfDocs = documents.map(i => i.getContent());
        console.log("Locations within a mile of corrdinate [30,30]")
        contentOfDocs.forEach(logIt);
        console.log();

    Les points renvoyés par cette requête sont les suivants :

    Locations within 60 miles of corrdinate [30,30]
    {"location":{"type":"Point","coordinates":[29.9,30.1]}}
    {"location":{"type":"Point","coordinates":[29.8,30.2]}}
    {"location":{"type":"Point","coordinates":[29.7,30.3]}}
    {"location":{"type":"Point","coordinates":[29.6,30.4]}}
    {"location":{"type":"Point","coordinates":[29.5,30.5]}}
    {"location":{"type":"Point","coordinates":[29.4,30.6]}}
    {"location":{"type":"Point","coordinates":[30,30]}}
    

    Indiquer [29.3,30.7] est à plus de 60 milles. Pour vérifier, j’utilise le calculateur de distance de latitude/longitude de la NOAA, qui montre que ce point est à 55 milles marins, soit 55 * 1,1508 = 63,3 milles terrestres.

    Pour voir toutes les unités de mesure disponibles, exécutez :

    select * from SDO_UNITS_OF_MEASURE;

    Il existe actuellement plus de 140 unités de mesure distinctes.

    Cette requête recherchera tous les points contenus dans le polygone spécifié à l’aide de la $within Opérateur QBE. Notez que les coordonnées sont spécifiées comme si vous dessiniez le polygone. C’est un carré spécifié par 5 points.

        // Find all within a polygon,in this case a box
        documents = await myCollection.find().filter({"location":{"$within":{"$geometry":{"type":"Polygon","coordinates":[[[29,30],[30,30],[30,31],[29,31],[29,30]]]}}}}).getDocuments();
        contentOfDocs = documents.map(i => i.getContent());
        console.log("Locations within specified polygon")
        contentOfDocs.forEach(logIt);
        console.log();

    Cette requête renvoie 9 points :

    Locations within specified polygon
    {"location":{"type":"Point","coordinates":[29.8,30.2]}}
    {"location":{"type":"Point","coordinates":[29.7,30.3]}}
    {"location":{"type":"Point","coordinates":[29.6,30.4]}}
    {"location":{"type":"Point","coordinates":[29.5,30.5]}}
    {"location":{"type":"Point","coordinates":[29.4,30.6]}}
    {"location":{"type":"Point","coordinates":[29.3,30.7]}}
    {"location":{"type":"Point","coordinates":[29.2,30.8]}}
    {"location":{"type":"Point","coordinates":[29.1,30.9]}}
    {"location":{"type":"Point","coordinates":[29.9,30.1]}}

    Le seul point non retourné est [30,30] qui est un point qui tombe sur le polygone et non à l’intérieur.
    Si vous aviez voulu tous les points sur la limite du polygone et dans l’espace polygonal fermé, le $intercepts L’opérateur QBE est fait pour vous.

        // Find all intersecting a polygon,in this case a box
        documents = await myCollection.find().filter({"location":{"$intersects":{"$geometry":{"type":"Polygon","coordinates":[[[29,30],[30,30],[30,31],[29,31],[29,30]]]}}}}).getDocuments();
        contentOfDocs = documents.map(i => i.getContent());
        console.log("Locations intersecting specified polygon")
        contentOfDocs.forEach(logIt);
        console.log();

    Cette requête renvoie l’ensemble complet des points créés au début de cette discussion.

    Locations intersecting specified polygon
    {"location":{"type":"Point","coordinates":[29.8,30.2]}}
    {"location":{"type":"Point","coordinates":[29.7,30.3]}}
    {"location":{"type":"Point","coordinates":[29.6,30.4]}}
    {"location":{"type":"Point","coordinates":[29.5,30.5]}}
    {"location":{"type":"Point","coordinates":[29.4,30.6]}}
    {"location":{"type":"Point","coordinates":[29.3,30.7]}}
    {"location":{"type":"Point","coordinates":[29.2,30.8]}}
    {"location":{"type":"Point","coordinates":[29.1,30.9]}}
    {"location":{"type":"Point","coordinates":[30,30]}}
    {"location":{"type":"Point","coordinates":[29.9,30.1]}}

    Il s’agissait d’un aperçu rapide de l’utilisation des opérateurs spatiaux fournis par la base de données Oracle JSON. Ces opérateurs aident…

    Share. Facebook Twitter Pinterest LinkedIn WhatsApp Reddit Email
    Add A Comment

    Leave A Reply Cancel Reply

    Catégories

    • Politique de cookies
    • Politique de confidentialité
    • CONTACT
    • Politique du DMCA
    • CONDITIONS D’UTILISATION
    • Avertissement
    © 2023 DéveloppeurWeb.Com.

    Type above and press Enter to search. Press Esc to cancel.