MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Verwenden einer Objekteigenschaft als $maxDistance-Argument in einer mongodb-Geolocation-Abfrage

Sie können das nicht ganz so machen – im Allgemeinen können Sie nichts in Ihren MongoDB-Abfragen auf Werten in den Sammlungen basieren.

Seit MongoDB 2.4 unterstützen wir jedoch einen neuen Index namens 2dsphere wodurch Sie nicht nur Punkte in der Datenbank speichern können, sondern auch Polygone. Sie speichern diese Informationen in einem Dokument wie:

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 ] ] ]
    }
} );

Und dann können Sie eine "Schnittmenge"-Abfrage verwenden, um herauszufinden, ob ein Punkt von jedem der Polygone abgedeckt wird:

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

Was dann zurückgibt:

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

Hier findet es die Feuerwache, denn 0, 0 liegt in der Mitte des Polygons. Jetzt besteht der Trick natürlich darin, die Polygonpunkte zu berechnen, die einen Kreis bilden, der einen "Radius" (z. B. 10 km) vom Mittelpunkt entfernt ist. Sie werden keinen echten Kreis bekommen, aber ein Sechseck oder Achteck sollte gut genug sein. Die Mathematik dafür ist nicht ganz einfach, aber http:// www.movable-type.co.uk/scripts/latlong.html#destPoint hat ein Beispiel in JavaScript. Schleifen Sie einfach Ihre Peilung in 8 Schritten von 0 bis 2PI, um die Punkte entlang des Umfangs des Kreises zu berechnen, und setzen Sie diese in die Koordinaten ein. Stellen Sie sicher, dass Sie sie in ein doppelt verschachteltes Array einbetten und das erste und das letzte gleich machen:

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