Encore plus optimal que l'original, vous pouvez désormais utiliser $expr
dans un $match
étape après le premier $geoNear
:
db.collection.aggregate([
{ "$geoNear": {
"near": {
"type": "Point",
"coordinates": [ 23.027573, 72.50675800000001 ],
},
"distanceField": "distance"
}},
{ "$match": { "$expr": { "$lte": [ "$distance", "$radius" ] } }}
])
En fait, un peu plus optimal que lors de la première écriture. Maintenant, nous pouvons simplement $redact
plutôt que $project
le booléen et $match
plus tard :
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"
}
}}
])
Vous avez stocké les informations exactement comme vous le devriez, mais l'approche pour obtenir les résultats est différente de celle que vous pensez.
Ce que vous voulez utiliser est un $geoNear
et plus précisément le framework d'agrégation
forme de cet opérateur. Voici ce que vous faites :
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 } }
])
Ainsi, cette forme permet de "projeter" la distance depuis le point interrogé dans les résultats, tandis que la requête ne renverra également que les documents les plus proches.
Ensuite, vous utilisez une comparaison logique pour voir si la valeur "distance" est inférieure à "rayon", donc à l'intérieur du cercle.
Enfin, vous faites correspondre pour filtrer uniquement les résultats où cette affirmation "dans" était vraie.
Vous pouvez ajouter d'autres options à $geoNear
comme indiqué dans la documentation. Je suggérerais également fortement que votre stockage utilise également le format GeoJSON car il est susceptible d'être plus compatible avec les autres bibliothèques que vous pourriez utiliser pour travailler sur les résultats obtenus.