Ja det är möjligt. Du använder bara $geoNear
istället. Akta dig för fångsterna och läs noga.
Förutsatt att din avsikt är att lagra ett fält som "travelDistance"
att ange på dokumentet att sådana sökningar måste vara "inom" det angivna avståndet från den frågade punkten för att vara giltiga. Sedan frågar och utvärderar vi helt enkelt villkoret med $redact
:
db.collection.aggregate([
{ "$geoNear": {
"near": {
"type": "Point",
"coordinates": [x,y]
},
"spherical": true,
"distanceField": "distance"
}},
{ "$redact": {
"$cond": {
"if": { "$lte": [ "$distance", "$travelDistance" ] },
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Den enda haken är att $geoNear
precis som $near
kommer bara att returnera ett visst antal dokument "nära" i första hand. Du kan justera det med alternativen, men till skillnad från det allmänna frågeformuläret är detta i princip en garanti för att de slutliga returnerade resultaten kommer att vara mindre än de angivna "närmaste" siffrorna.
Så länge du är medveten om det, så är detta fullt giltigt.
Det är faktiskt det allmänna sättet att hantera att kvalificera det som är "nära" inom en radie.
Var också uppmärksam på "avståndet" enligt hur du har koordinaterna lagrade. Som äldre koordinatpar kommer avstånden att vara i radianer som du förmodligen kommer att behöva räkna ut för att konvertera till kilometer eller miles.
Om du använder GeoJSON, betraktas avstånden alltid i meter, som standardformat.
Alla matematiknoteringar finns i dokumentationen.
OBS Läs
$geoNear
dokumentation noggrant. Alternativ som"spherical"
krävs för"2dsphere"
index, som du borde ha för verkliga koordinater. Även"limit"
kan behöva tillämpas för att öka förbi standardresultatet för 100 dokument, för ytterligare trimning.
Eftersom kommentarerna nämner vårmongo, så görs här i princip samma sak för det:
Aggregation aggregation = newAggregation(
new AggregationOperation() {
@Override
public DBObject toDBObject(AggregationOperationContext context) {
return new BasicDBObject("$geoNear",
new BasicDBObject(
"near", new BasicDBObject(
"type","Point")
.append("coordinates", Arrays.asList(20,30))
)
.append("spherical",true)
.append("distanceField","distance")
);
}
},
new AggregationOperation() {
@Override
public DBObject toDBObject(AggregationOperationContext context) {
return new BasicDBObject("$redact",
new BasicDBObject(
"$cond", Arrays.asList(
new BasicDBObject("$lte", Arrays.asList("$distance", "$travelDistance")),
"$$KEEP",
"$$PRUNE"
)
)
);
}
}
);