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

Geospacial Query Spheres von MongoDB überlappen einen einzelnen Punkt

Nun, es wäre schöner, wenn Sie ein GeoJSON-Objekt verwenden könnten, um den Standort darzustellen, aber derzeit ist der unterstützte Typen sind tatsächlich begrenzt daher wird ein "Circle"-Typ, der ideal wäre, nicht unterstützt.

Das Beste, was Sie tun könnten, wäre ein "Polygon", das sich einem Kreis annähert, aber das ist wahrscheinlich ein wenig zu viel Arbeit, um es nur für diesen Abfragezweck zu konstruieren. Der andere hat damit zu tun und dann $geoIntersects ist, dass die Ergebnisse nicht nach der Entfernung vom Abfragepunkt "sortiert" werden. Das scheint das Gegenteil des Zwecks zu sein, die "nächste Pizza" zum Ursprungsort zu finden.

Glücklicherweise gibt es einen $geoNear -Operation zum Aggregationsframework ab MongoDB 2.4 und höher hinzugefügt. Das Gute dabei ist, dass es die "Projektion" eines Entfernungsfeldes in die Ergebnisse erlaubt. Auf diese Weise können Sie dann die logische Filterung auf dem Server für die Punkte durchführen, die sich "innerhalb des Radius" befinden, der auf die Entfernung vom Ursprungspunkt beschränkt ist. Es ermöglicht auch das Sortieren auf dem Server.

Aber Sie müssen Ihr Schema trotzdem ändern, um den Index zu unterstützen

db.places.insert({
    "name": "Pizza Hut",
    "location": { 
        "type": "Point",
        "coordinates": [
            151.00211262702942,
            -33.81696995135973
        ]
    },
    "radius": 20
})

db.places.ensureIndex({ "location": "2dsphere" })

Und für die Aggregationsabfrage:

db.places.aggregate([

    // Query and project distance
    { "$geoNear": {
        "near": { 
            "type": "Point",
            "coordinates": [ 
                150.92094898223877,
                -33.77654333272719
            ]
        },
        "distanceField": "distance",
        "distanceMultiplier": 0.001,
        "maxDistance": 100000,
        "spherical": true
    }},

    // Calculate if distance is within delivery sphere
    { "$project": {
         "name": 1,
         "location": 1,
         "radius": 1,
         "distance": 1,
         "within": { "$gt": [ "$radius", "$distance" ] }
    }},

    // Filter any false results
    { "$match": { "within": true } },

    // Sort by shortest distance from origin
    { "$sort": { "distance": -1 } }
])

Im Grunde sagt dies,

Es gibt andere Optionen, die Sie an $geoNear um das Ergebnis zu verfeinern sowie bei Bedarf mehr als die standardmäßigen 100 Ergebnisse zurückzugeben und grundsätzlich andere Abfrageoptionen wie "Typ" oder "Name" oder andere Informationen, die Sie im Dokument haben, zu übergeben.