Reputation: 6168
I have following sample mongodb document in the collection offers
.
{
"countryCode" : "LU",
"geoLocation" : [
{
"lat" : 49.8914114000000026,
"lng" : 6.0950994999999999
}
]
},
{
"countryCode" : "DE",
"geoLocation" : [
{
"lat" : 50.8218536999999984,
"lng" : 9.0202151000000015
}
]
}
Fetch the document based on the geolocation which is around 50km radius
db.getCollection('offers').aggregate([
{
$geoNear: {
near: [6.0950994999999999, 49.8914114000000026],
distanceField: "geoLocation",
maxDistance: 50000, //50 km radius
}
}
]);
It is fetching all the documents instead of searching around 50km.
Any suggestion will be grateful.
Upvotes: 2
Views: 2141
Reputation: 50406
Legacy coordinate pairs do not return distances in meters, but in radians instead. Your maxDistance therefore much larger than 50km. See Calculate Distances with Spherical Geometry
But also consider the actual distance being used here:
db.getCollection('offers').aggregate([
{
$geoNear: {
near: [6.0950994999999999, 49.8914114000000026],
distanceField: "distance"
}
]);
Returns:
{
"_id" : ObjectId("55dc0f4b6f07ad5d3ec3b6d0"),
"countryCode" : "DE",
"geoLocation" : [
{
"lat" : 50.8218537,
"lng" : 9.020215100000001
}
],
"distance" : 60.588259822017925
}
{
"_id" : ObjectId("55dc0f4b6f07ad5d3ec3b6cf"),
"countryCode" : "LU",
"geoLocation" : [
{
"lat" : 49.8914114,
"lng" : 6.0950995
}
],
"distance" : 61.93733827090219
}
As the "distanceField" is meant to be the field that reports the projected distance from the queried point.
So the start point is that your documents are ot valid for geoSpatial queries. Fix them like this:
First drop all indexes:
db.offers.dropIndexes();
Then fix the fields:
var bulk = db.offers.initializeOrderedBulkOp(),
count = 0;
db.offers.find({}).forEach(function(doc) {
//printjson(doc);
var tmp = {
"type": "Point",
"coordinates": [doc.geoLocation[0].lng,doc.geoLocation[0].lat]
};
doc.geoLocation = tmp;
printjson(doc);
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "geoLocation": doc.geoLocation }
});
count++;
if ( count % 1000 == 0 ) {
bulk.execute();
bulk = db.offers.initializeOrderedBulkOp();
}
});
Now the data is represented in a correct GeoJSON format:
{
"_id" : ObjectId("55dc14856f07ad5d3ec3b6d1"),
"countryCode" : "LU",
"geoLocation" : {
"type" : "Point",
"coordinates" : [
6.0950995,
49.8914114
]
}
}
{
"_id" : ObjectId("55dc14856f07ad5d3ec3b6d2"),
"countryCode" : "DE",
"geoLocation" : {
"type" : "Point",
"coordinates" : [
9.020215100000001,
50.8218537
]
}
}
Now create an index as 2dsphere:
db.offers.createIndex({ "geoLocation": "2dsphere" })
Now you are ready to query:
db.offers.aggregate([
{ "$geoNear": {
"near": {
"type": "Point",
"coordinates": [6.0950994999999999, 49.8914114000000026]
},
"distanceField": "distance",
"spherical": true,
"maxDistance": 50000
}}
])
Which returns the one document that is "near", or in fact 0 distance:
{
"_id" : ObjectId("55dc14856f07ad5d3ec3b6d1"),
"countryCode" : "LU",
"geoLocation" : {
"type" : "Point",
"coordinates" : [
6.0950995,
49.8914114
]
},
"distance" : 0
}
Upvotes: 4