sql >> Base de Datos >  >> NoSQL >> MongoDB

Encuentra una ubicación dentro de un círculo almacenado

Aún más óptimo que el original, ahora puede usar $expr dentro de un $match etapa después de la inicial $geoNear :

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

En realidad, un poco más óptimo que cuando se escribió por primera vez. Ahora podemos simplemente $redact en lugar de $project el booleano y $match más tarde:

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

Has almacenado la información exactamente como deberías, pero hay un enfoque diferente para obtener los resultados de lo que piensas.

Lo que quiere usar es un $geoNear y específicamente el marco de agregación forma de ese operador. Esto es lo que haces:

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

Entonces ese formulario permite "proyectar" la distancia desde el punto consultado en los resultados, mientras que la consulta solo devolverá los documentos más cercanos.

Luego usa una comparación lógica para ver si el valor de "distancia" es menor que "radio", por lo tanto, dentro del círculo.

Finalmente, hace coincidir para filtrar solo aquellos resultados en los que la afirmación "dentro" era cierta.

Puede agregar otras opciones a $geoNear como se muestra en la documentación. También recomendaría encarecidamente que su almacenamiento también use el formato GeoJSON, ya que es probable que sea más compatible con cualquier otra biblioteca que pueda usar para trabajar en los resultados obtenidos.