はい、可能です。 $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ドキュメントの結果を超えて増やすために適用する必要がある場合があります。
コメントが春のmongoに言及しているように、これは基本的に同じことです:
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"
)
)
);
}
}
);