Да, възможно е. Просто използвате $geoNear
вместо. Пазете се от уловките и прочетете внимателно.
Предполагайки, че намерението ви е да съхраните поле като "travelDistance"
за да посочите в документа, че всяко такова търсене трябва да бъде "в рамките" на това предоставено разстояние от запитаната точка, за да бъде валидно. След това просто правим заявка и оценяваме условието с $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"
}
}}
])
Единствената уловка е, че $geoNear
точно като $near
ще върне само определен брой документи "близо" на първо място. Можете да настроите това с опциите, но за разлика от общата форма на заявка, това по същество гарантира, че евентуалните върнати резултати ще бъдат по-малко от посочените „най-близки“ числа.
Докато сте наясно с това, това е напълно валидно.
Всъщност това е общият начин за справяне с квалифицирането на това, което е „близо“ в радиус.
Също така имайте предвид „разстоянието“ в зависимост от това как съхранявате координатите. Като наследени координатни двойки, разстоянията ще бъдат в радиани, които вероятно ще трябва да направите математиката, за да ги преобразувате в километри или мили.
Ако използвате GeoJSON, тогава разстоянията винаги се разглеждат в метри, като стандартен формат.
Всички бележки по математика са в документацията.
N.B Прочетете
$geoNear
документация внимателно. Опции като"spherical"
са необходими за"2dsphere"
индекси, каквито трябва да имате за координатите в реалния свят. Също така"limit"
може да се наложи да се приложи, за да се увеличи над резултата от документа по подразбиране от 100, за по-нататъшно изрязване.
Тъй като в коментарите се споменава пролетно монго, ето основно същото нещо, което е направено за това:
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"
)
)
);
}
}
);