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

Finden Sie einen Ort innerhalb eines gespeicherten Kreises

Noch optimaler als das Original können Sie jetzt $expr innerhalb eines $match Phase nach dem anfänglichen $geoNear :

db.collection.aggregate([
    { "$geoNear": {
        "near": {
            "type": "Point",
            "coordinates": [ 23.027573, 72.50675800000001 ],
        },
        "distanceField": "distance"
    }},
    { "$match": { "$expr": { "$lte": [ "$distance", "$radius" ] } }}
])

Eigentlich etwas optimaler als zu Beginn geschrieben. Jetzt können wir einfach $redact statt $project der boolesche Wert und $match später:

db.collection.aggregate([
    // Match documents "near" the queried point
    { "$geoNear": {
        "near": {
            "type": "Point",
            "coordinates": [ 23.027573, 72.50675800000001 ],
        },
        "distanceField": "distance"
    }},

    // Calculate if distance is within radius and remove if not
    { "$redact": {
        "$cond": {
            "if": { "$lte": [ "$distance", "$radius" ] },
            "then": "$$KEEP",
            "else": "$$PRUNE"
        }
    }}
])

Sie haben die Informationen genau so gespeichert, wie Sie es sollten, aber es gibt einen anderen Ansatz, um die Ergebnisse zu erhalten, als Sie denken.

Was Sie verwenden möchten, ist ein $geoNear und insbesondere das Aggregations-Framework Form dieses Operators. So gehen Sie vor:

db.collection.aggregate([
    // Match documents "near" the queried point
    { "$geoNear": {
        "near": {
            "type": "Point",
            "coordinates": [ 23.027573, 72.50675800000001 ],
        },
        "distanceField": "distance"
    }},

    // Calculate if distance is within radius
    { "$project": {
        "location": 1,
        "radius": 1,
        "distance": 1,
        "within": { "$lte": [ "$distance", "$radius" ] }
    }},

    // Match only documents within the radius
    { "$match": { "within": true } }
])

Dieses Formular ermöglicht es also, die Entfernung vom abgefragten Punkt in die Ergebnisse "hochzurechnen", während die Abfrage auch nur die nächstgelegenen Dokumente zurückgibt.

Dann sehen Sie mit einem logischen Vergleich, ob der Wert für "Distanz" kleiner als "Radius" ist, also innerhalb des Kreises.

Schließlich passen Sie an, um nur die Ergebnisse herauszufiltern, bei denen diese "innerhalb"-Behauptung wahr war.

Sie können $geoNear weitere Optionen hinzufügen wie in der Dokumentation gezeigt. Ich würde auch dringend empfehlen, dass Ihr Speicher auch das GeoJSON-Format verwendet, da dies wahrscheinlich besser mit anderen Bibliotheken kompatibel ist, die Sie möglicherweise verwenden, um an den erzielten Ergebnissen zu arbeiten.