Iya itu mungkin. Anda cukup menggunakan $geoNear
sebagai gantinya. Waspadalah terhadap tangkapan dan bacalah dengan cermat.
Anggap bahwa maksud Anda adalah untuk menyimpan bidang seperti "travelDistance"
untuk menunjukkan pada dokumen bahwa pencarian semacam itu harus "dalam" jarak yang disediakan dari titik pertanyaan agar valid. Kemudian kita cukup query dan evaluasi kondisi dengan $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"
}
}}
])
Satu-satunya tangkapan adalah $geoNear
seperti $near
hanya akan mengembalikan sejumlah dokumen "dekat" di tempat pertama. Anda dapat menyetelnya dengan opsi, tetapi tidak seperti formulir kueri umum, ini pada dasarnya menjamin bahwa hasil yang dikembalikan pada akhirnya akan kurang dari angka "terdekat" yang ditentukan.
Selama Anda menyadarinya, maka ini sah-sah saja.
Sebenarnya ini adalah cara umum untuk menangani kualifikasi yang "dekat" dalam radius.
Perhatikan juga "jarak" menurut cara Anda menyimpan koordinat. Sebagai pasangan koordinat lama, jaraknya akan dalam radian yang mungkin perlu Anda hitung untuk mengubahnya menjadi kilometer atau mil.
Jika menggunakan GeoJSON, maka jarak selalu dianggap dalam meter, sebagai format standar.
Semua catatan matematika ada di dokumentasi.
N.B Baca
$geoNear
dokumentasi dengan cermat. Opsi seperti"spherical"
diperlukan untuk"2dsphere"
indeks, seperti yang harus Anda miliki untuk koordinat dunia nyata. Juga"limit"
mungkin perlu diterapkan untuk meningkatkan melewati hasil 100 dokumen default, untuk pemangkasan lebih lanjut.
Seperti komentar yang menyebutkan spring mongo, maka pada dasarnya hal yang sama dilakukan untuk itu:
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"
)
)
);
}
}
);