Blog ENI : Toute la veille numérique !
-25€ dès 75€ sur les livres en ligne, vidéos... avec le code FUSEE25. J'en profite !
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
  1. Livres et vidéos
  2. MongoDB
  3. Les requêtes géospatiales
Extrait - MongoDB Comprendre et optimiser l'exploitation de vos données (avec exercices et corrigés)
Extraits du livre
MongoDB Comprendre et optimiser l'exploitation de vos données (avec exercices et corrigés) Revenir à la page d'achat du livre

Les requêtes géospatiales

Introduction

Nous savons maintenant qu’il convient d’utiliser des objets GeoJSON pour réaliser des requêtes géospatiales. Voici une collection exemple nommée avignon qui recense certains des monuments importants et endroits remarquables de la cité papale. Ces endroits sont tous matérialisés sous la forme d’objets GeoJSON de type Point :

db.avignon.insertMany([{ 
   "nom": "Palais des Papes", 
   "localisation": { 
       "coordinates": [43.9507, 4.8075], 
       "type": "Point" 
   } 
}, 
{ 
   "nom": "Pont Saint-Bénézet", 
   "localisation": { 
       "coordinates": [43.95397, 4.80478], 
       "type": "Point" 
   } 
}, 
{ 
   "nom": "Collection Lambert", 
   "localisation": { 
       "coordinates": [43.944787, 4.804031], 
       "type": "Point" 
   } 
}]) 

Nous créons immédiatement un index de type 2dsphere sur le champ localisation de notre...

L’opérateur $nearSphere

Cet opérateur requiert un index géospatial de type 2dsphere quand on l’utilise avec des objets GeoJSON et un index 2d quand il est utilisé avec des coordonnées de type legacy. Lorsqu’il opère sur des objets GeoJSON de type Point, sa syntaxe est :

{ 
 $nearSphere: { 
    $geometry: { 
       type : "Point", 
       coordinates : [ <longitude>, <latitude> ] 
    }, 
    $minDistance: <distance en mètres>, 
    $maxDistance: <distance en mètres> 
 } 
} 

Les champs $minDistance et $maxDistance sont optionnels et leur unité de mesure est le mètre.

Lorsqu’il travaille avec des coordonnées de type legacy, l’opérateur possède cette forme-ci :

{ 
 $nearSphere: [ <x>, <y> ], 
 $minDistance: <distance en radians>, 
 $maxDistance: <distance en radians> 
} 

Les champs $minDistance et $maxDistance sont là aussi optionnels, mais leur unité de mesure est le radian et non plus le mètre. Nous l’avons déjà évoqué, mais retenez que lorsque x et y matérialisent des coordonnées géographiques la longitude doit toujours être précisée en premier.

Qu’il travaille avec des objets GeoJSON ou des coordonnées legacy, $nearSphere retourne les documents triés par ordre croissant de distance par rapport au point matérialisant le centre de la recherche. Il est possible de les ordonner différemment en effectuant un sort qui prendra le pas sur le tri effectué de manière native par $nearSphere mais, afin d’éviter d’écraser ce pré-tri, il est préférable d’utiliser l’opérateur $geoNear, qui n’en effectue pas.

Effectuons deux requêtes pour utiliser $nearSphere dans sa version « dépouillée », c’est-à-dire sans aucun des champs optionnels.

Notre...

L’opérateur $geoWithin

Cet opérateur permet de capturer des documents dont les données géospatiales résident entièrement à l’intérieur d’une forme définie sous la forme d’objets GeoJSON matérialisant un polygone ou un multipolygone (respectivement nommées Polygon et MultiPolygon) ou bien d’une forme définie par des coordonnées legacy.

Contrairement à $nearSphere, l’opérateur $geoWithin n’effectue pas de pré-tri avant l’affichage et ne requiert pas d’indexation géospatiale, bien qu’il soit toutefois conseillé d’utiliser un index 2dsphere ou 2d afin d’optimiser les performances des requêtes.

Pour les zones représentées par des formes dont la surface est égale ou supérieure à la taille d’un hémisphère, MongoDB utilise son propre Système de Coordonnées de Référence (SCR).

Commençons tout d’abord par créer un polygone qui exclut l’un des trois documents symbolisés par un marqueur orange sur notre carte.

images/04EP02.png

Nous stockerons ses coordonnées dans une variable JavaScript nommée polygone avant d’en faire usage dans notre première requête utilisant $geoWithin. Cette requête opérera sur la collection avignon2d en passant en paramètre notre polygone. Voyons d’abord la syntaxe de notre opérateur lorsqu’il travaille avec des coordonnées legacy sur une surface plane :

{ 
     <champ des documents contenant les coordonnées>: { 
            $geoWithin: { 
                   < opérateur de forme >: < coordonnées > 
            } 
     } 
} 

Le champ contenant les coordonnées dans nos documents n’a pas changé, notre opérateur de forme sera $polygon et les coordonnées seront contenues dans le tableau de paires longitude/latitude que voici :...

L’opérateur $geoIntersects

Cet opérateur sélectionne les documents dont l’intersection des données géospatiales avec des objets GeoJSON est non-vide. Sa syntaxe prend cette forme-ci :

{ 
     <champ des documents contenant les coordonnées>: { 
           $geoIntersects: { 
               $geometry: { 
                   "type": < Tout type d'objet GeoJSON>  , 
                   "coordinates": [ < coordonnées > ] 
               } 
           } 
     } 
} 

Nous allons, afin d’utiliser l’opérateur $geoIntersects, créer des intersections de polygones au niveau du polygone nommé polygone2. Voici ce à quoi va ressembler notre carte d’Avignon une fois mise à jour :

images/04EP04.png

Notre polygone originel est situé à gauche, nous lui avons ajouté deux triangles :

  • un triangle au centre, que nous nommerons polygone2bis

  • un triangle à droite, que nous nommerons polygone2ter.

Nous insérons dans notre collection avignon (qui ne contient que des points)...