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.