MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Utilisation d'une propriété d'objet comme argument $maxDistance dans une requête de géolocalisation mongodb

Vous ne pouvez pas tout à fait faire cela comme ceci - en général, vous ne pouvez rien baser dans vos requêtes MongoDB sur les valeurs des collections.

Cependant, depuis MongoDB 2.4, nous prenons en charge un nouvel index appelé 2dsphere qui vous permet de stocker non seulement des points dans la base de données, mais également des polygones. Vous stockeriez ces informations dans un document tel que :

db.so.ensureIndex( { loc: '2dsphere' } );
db.so.insert( {
    name: "Firestation 1",
    loc: {
        type: "Polygon",
        coordinates: [ [ [ 0, 0 ], [ 0, 1 ], [ 1, 1 ], [ 1, 0 ], [ 0, 0 ] ] ]
    }
} );

Et ensuite, vous pouvez utiliser une requête "intersection" pour déterminer si un point est couvert par chacun des polygones :

db.so.find( {
    'loc' : {  
        $geoIntersects: { 
            $geometry: { type: 'Point', coordinates: [ 0, 0 ] } 
        } 
    }
} );

Qui renvoie alors :

{ 
    "_id" : ObjectId("51f24d566775068ab0b786f0"), 
    "name" : "Firestation 1", 
    "loc" : { 
        "type" : "Polygon", 
        "coordinates" : [  [  [  0,  0 ],  [  0,  1 ],  [  1,  1 ],  [  1,  0 ],  [  0,  0 ] ] ] 
    } 
}

Ici, il trouve la caserne des pompiers, car 0, 0 est au milieu du polygone. Maintenant, l'astuce consiste bien sûr à calculer les points du polygone qui composent un cercle dont le "rayon" (disons 10 km) est éloigné du point central. Vous ne pourrez pas obtenir un vrai cercle, mais un hexagone ou un octogone devrait suffire. Le calcul pour cela n'est pas extrêmement simple, mais http:// www.movable-type.co.uk/scripts/latlong.html#destPoint a un exemple en JavaScript.Il suffit de boucler votre relèvement en 8 étapes de 0 à 2PI pour calculer les points le long de la circonférence du cercle, et de les mettre dans les coordonnées. Assurez-vous de les intégrer dans un tableau doublement imbriqué et de faire en sorte que le premier et le dernier soient identiques :

{
    name: "Firestation 1",
    loc: {
        type: "Polygon",
        coordinates: [ [
            [ point1-lon, point1-lat ], 
            [ point2-lon, point2-lat ], 
            [ point3-lon, point3-lat ], 
            ...
            [ point1-lon, point1-lat ], 
        ] ]
    }
}