MongoDB 3.0.4 $nearSphere $maxDistance strange behaviour - mongodb

I have a question about distance measuring in a $maxDistance. I have document:
{
"location": {
{ "type" : "Point", "coordinates" : [ 38.8993487, -77.0145665 ] }
}
}
Making a query in a shell:
db.places.find({"location": {"$nearSphere": {"$geometry": {"type":"Point", "coordinates": [38.888684, -77.0047189]}, "$maxDistance": 1129 } }})[0].location
Returns a
{ "type" : "Point", "coordinates" : [ 38.8993487, -77.0145665 ] }
But distance measurement made by gpsvisualizer.com shows me 1.4600 km. Mongo have a result with maxDistance set to 1129 meters
So my question is - what did I miss ?:D

I think you missing the fact that mongoDB’s 2d spherical index operators only recognize [longitude, latitude] ordering. Correct link would be: gpsvisualiser. As you can see, distance between those points is about 1,13km :)

Related

Return distance for each coordinates in mongodb [duplicate]

When I am firing this query on MongoDB, I am getting all the places in the proximity of 500 miles to the specified co-ordinates. But I want to know the exact distance between the specified co-ordinates and the result location.
db.new_stores.find({ "geometry": { $nearSphere: { $geometry: { type: "Point", coordinates: [ -81.093699, 32.074673 ] }, $maxDistance: 500 * 3963 } } } ).pretty()
My Output looks like:
{
"_id" : ObjectId("565172058bc200b0db0f75b1"),
"type" : "Feature",
"geometry" : {
"type" : "Point",
"coordinates" : [
-80.148826,
25.941116
]
},
"properties" : {
"Name" : "Anthony's Coal Fired Pizza",
"Address" : "17901 Biscayne Blvd, Aventura, FL"
}
}
I also want to know the distance of this place from the specified co-ordinate. I created 2dsphere index on geometry.
You can use the $geoNear aggregate pipeline stage to produce a distance from the queried point:
db.new_stores.aggregate([
{ "$geoNear": {
"near": {
"type": "Point",
"coordinates": [ -81.093699, 32.074673 ]
},
"maxDistance": 500 * 1609,
"key" : "myLocation",
"spherical": true,
"distanceField": "distance",
"distanceMultiplier": 0.000621371
}}
]).pretty()
This allows you to specify "distanceField" which will produce another field in the output documents containing the distance from the queried point. You can also use "distanceMultiplier" to apply any conversion to the output distance as required ( i.e meters to miles, and noting that all GeoJSON distances are returned in meters )
There is also the geoNear command with similar options, but it of course does not return a cursor as output.
if you have more than one 2dsphere, you should specify a "key".
MongoDB provides a $geoNear aggregator for calculating the distance of documents in a collection with GeoJson coordinates.
Let us understand it with a simple example.
Consider a simple collection shops
1. Create Collection
db.createCollection('shops')
2. Insert documents in shops collections
db.shops.insert({name:"Galaxy store",address:{type:"Point",coordinates:[28.442894,77.341299]}})
db.shops.insert({name:"A2Z store",address:{type:"Point",coordinates:[28.412894,77.311299]}})
db.shops.insert({name:"Mica store",address:{type:"Point",coordinates:[28.422894,77.342299]}})
db.shops.insert({name:"Full Stack developer",address:{type:"Point",coordinates:[28.433894,77.334299]}})
3. create GeoIndex on "address" fields
db.shops.createIndex({address: "2dsphere" } )
4. Now use a $geoNear aggregator
to find out the documents with distance.
db.shops.aggregate([{$geoNear:{near:{type:"Point",coordinates:[28.411134,77.331801]},distanceField: "shopDistance",$maxDistance:150000,spherical: true}}]).pretty()
Here coordinates:[28.411134,77.331801] is the center position or quired position from where documents will be fetched.
distanceField:"shopDistance" , $geoNear Aggregator return shopDistance as fields in result.
Result:
{ "_id" : ObjectId("5ef047a4715e6ae00d0893ca"), "name" : "Full Stack developer", "address" : { "type" : "Point", "coordinates" : [ 28.433894, 77.334299 ] }, "shopDistance" : 621.2848190449148 }
{ "_id" : ObjectId("5ef0479e715e6ae00d0893c9"), "name" : "Mica store", "address" : { "type" : "Point", "coordinates" : [ 28.422894, 77.342299 ] }, "shopDistance" : 1203.3456146763526 }
{ "_id" : ObjectId("5ef0478a715e6ae00d0893c7"), "name" : "Galaxy store", "address" : { "type" : "Point", "coordinates" : [ 28.442894, 77.341299 ] }, "shopDistance" : 1310.9612119555288 }
{ "_id" : ObjectId("5ef04792715e6ae00d0893c8"), "name" : "A2Z store", "address" : { "type" : "Point", "coordinates" : [ 28.412894, 77.311299 ] }, "shopDistance" : 2282.6640175038788 }
Here shopDistance will be in meter.
maxDistance -> Optional. The maximum distance from the center point that the documents can be. MongoDB limits the results to those documents that fall within the specified distance from the center point.
Specify the distance in meters if the specified point is GeoJSON and in radians if the specified point is legacy coordinate pairs.
In the docs it says if you use legacy pairs , eg : near : [long , lat] , then specify the maxDistance in radians.
If you user GeoJSON , eg : near : { type : "Point" , coordinates : [long ,lat] },
then specify the maxDistance in meters.
Use $geoNear to get the distance between a given location and users.
db.users.aggregate([
{"$geoNear": {
"near": {
"type": "Point",
"coordinates": [ longitude, latitude]
},
"distanceField": "distance",
"distanceMultiplier": 1/1000,
"query": {/* userConditions */},
}}
]).pretty()

MongoDB print distance between two points

When I am firing this query on MongoDB, I am getting all the places in the proximity of 500 miles to the specified co-ordinates. But I want to know the exact distance between the specified co-ordinates and the result location.
db.new_stores.find({ "geometry": { $nearSphere: { $geometry: { type: "Point", coordinates: [ -81.093699, 32.074673 ] }, $maxDistance: 500 * 3963 } } } ).pretty()
My Output looks like:
{
"_id" : ObjectId("565172058bc200b0db0f75b1"),
"type" : "Feature",
"geometry" : {
"type" : "Point",
"coordinates" : [
-80.148826,
25.941116
]
},
"properties" : {
"Name" : "Anthony's Coal Fired Pizza",
"Address" : "17901 Biscayne Blvd, Aventura, FL"
}
}
I also want to know the distance of this place from the specified co-ordinate. I created 2dsphere index on geometry.
You can use the $geoNear aggregate pipeline stage to produce a distance from the queried point:
db.new_stores.aggregate([
{ "$geoNear": {
"near": {
"type": "Point",
"coordinates": [ -81.093699, 32.074673 ]
},
"maxDistance": 500 * 1609,
"key" : "myLocation",
"spherical": true,
"distanceField": "distance",
"distanceMultiplier": 0.000621371
}}
]).pretty()
This allows you to specify "distanceField" which will produce another field in the output documents containing the distance from the queried point. You can also use "distanceMultiplier" to apply any conversion to the output distance as required ( i.e meters to miles, and noting that all GeoJSON distances are returned in meters )
There is also the geoNear command with similar options, but it of course does not return a cursor as output.
if you have more than one 2dsphere, you should specify a "key".
MongoDB provides a $geoNear aggregator for calculating the distance of documents in a collection with GeoJson coordinates.
Let us understand it with a simple example.
Consider a simple collection shops
1. Create Collection
db.createCollection('shops')
2. Insert documents in shops collections
db.shops.insert({name:"Galaxy store",address:{type:"Point",coordinates:[28.442894,77.341299]}})
db.shops.insert({name:"A2Z store",address:{type:"Point",coordinates:[28.412894,77.311299]}})
db.shops.insert({name:"Mica store",address:{type:"Point",coordinates:[28.422894,77.342299]}})
db.shops.insert({name:"Full Stack developer",address:{type:"Point",coordinates:[28.433894,77.334299]}})
3. create GeoIndex on "address" fields
db.shops.createIndex({address: "2dsphere" } )
4. Now use a $geoNear aggregator
to find out the documents with distance.
db.shops.aggregate([{$geoNear:{near:{type:"Point",coordinates:[28.411134,77.331801]},distanceField: "shopDistance",$maxDistance:150000,spherical: true}}]).pretty()
Here coordinates:[28.411134,77.331801] is the center position or quired position from where documents will be fetched.
distanceField:"shopDistance" , $geoNear Aggregator return shopDistance as fields in result.
Result:
{ "_id" : ObjectId("5ef047a4715e6ae00d0893ca"), "name" : "Full Stack developer", "address" : { "type" : "Point", "coordinates" : [ 28.433894, 77.334299 ] }, "shopDistance" : 621.2848190449148 }
{ "_id" : ObjectId("5ef0479e715e6ae00d0893c9"), "name" : "Mica store", "address" : { "type" : "Point", "coordinates" : [ 28.422894, 77.342299 ] }, "shopDistance" : 1203.3456146763526 }
{ "_id" : ObjectId("5ef0478a715e6ae00d0893c7"), "name" : "Galaxy store", "address" : { "type" : "Point", "coordinates" : [ 28.442894, 77.341299 ] }, "shopDistance" : 1310.9612119555288 }
{ "_id" : ObjectId("5ef04792715e6ae00d0893c8"), "name" : "A2Z store", "address" : { "type" : "Point", "coordinates" : [ 28.412894, 77.311299 ] }, "shopDistance" : 2282.6640175038788 }
Here shopDistance will be in meter.
maxDistance -> Optional. The maximum distance from the center point that the documents can be. MongoDB limits the results to those documents that fall within the specified distance from the center point.
Specify the distance in meters if the specified point is GeoJSON and in radians if the specified point is legacy coordinate pairs.
In the docs it says if you use legacy pairs , eg : near : [long , lat] , then specify the maxDistance in radians.
If you user GeoJSON , eg : near : { type : "Point" , coordinates : [long ,lat] },
then specify the maxDistance in meters.
Use $geoNear to get the distance between a given location and users.
db.users.aggregate([
{"$geoNear": {
"near": {
"type": "Point",
"coordinates": [ longitude, latitude]
},
"distanceField": "distance",
"distanceMultiplier": 1/1000,
"query": {/* userConditions */},
}}
]).pretty()

MongoDB geoNear command result distance in kilometer

I am using mongoDB to store GPS locations data as this GeoJSON document
{"type" : "Point", "coordinates" : [33.313183, 44.465632]}
{"type" : "Point", "coordinates" : [33.2926487, 44.4159651]}
Update: I also ensured 2dspher index like follow
db.test.ensureIndex( { loc : "2dsphere" } )
I got the coordinates from Google maps
Now if I search using this command I cant convert the distances in result to kilometers
db.runCommand({geoNear: 'test', spherical: true, near: {type: "Point" , coordinates: [33.2926487, 44.4159651]}})
the result is as follow
"results" : [
{
"dis" : 0.0033427770982422957,
"obj" : {
"_id" : ObjectId("54a96f348fa05fcaed637a22"),
"loc" : {
"type" : "Point",
"coordinates" : [
33.2926487,
44.4159651
]
}
}
},
{
"dis" : 5764.7060911604085,
"obj" : {
"_id" : ObjectId("54a96f4c8fa05fcaed637a23"),
"loc" : {
"type" : "Point",
"coordinates" : [
33.313183,
44.465632
]
}
}
}
]
the first result is expected to be Zero since its the same point that I want to get the distance from source = destination coordinates, but still has value.
the second value I cant convert to Kilometers, in Google distance calculator is about 5.26KM.
As I continued my research about this issue I found this
there is two types of storing type for points
legacy point as this format
db.test2.insert({location: [33.313183, 44.465632]})
and GeoJSON point as this format
db.test.insert({location: {"type" : "Point", "coordinates" : [33.313183, 44.465632]}})
if we are using the legacy point the result would be in radian so we would convert it to kilometers using this statement
db.runCommand({geoNear: 'test2', spherical: true, near: [33.2926487, 44.4159651], distanceMultiplier: 6371})
if we are using GeoJSON point the result would be in meters so we would convert it to kilometers using this statement as this answer to this question
db.runCommand({geoNear: 'test', spherical: true, near: {type: "Point" , coordinates: [33.2926487, 44.4159651]}, distanceMultiplier: 0.001})
solution in case of GeoJSON point format
for more details check this link, a bug report to MongoDB that explains it all.
The distances are being returned in meters. To convert to kilometers, divide by 1000. You can have MongoDB do this using the distanceMultiplier option:
db.runCommand({ "geoNear" : "test", "spherical" : true, "distanceMultiplier" : 0.001, "near" : { "type" : "Point" , "coordinates" : [33.2926487, 44.4159651] } })
Did you index the field as a 2dsphere. That could explain the discrepancy since you're querying as sphere: true

MongoDB: Using $geoIntersects or $geoWithin with $near in one query

I would like to query for all documents that have a polygon that a point is contained in and then for that result set, order it based on closeness of that point to the location of the document.
So imagine I have a database of friends because I'm just that cool, and would like to see which friends are within the my range and would be willing to come play. (each friend has a play-date polygon which is the range they are willing to travel for a play-date)
For all matches I would like to them proceed to see which friend I should call to come based on his actual address and its distance to my point (which is my address) so that I can determine if I am ok with them coming from far away. (lets say 300 meters)
So far I have below a query to find polygons that my point is contained within but I do not know how to include the $near operator of mongodb
For JSON:
{
"_id" : "objid",
"FRIEND_NAME" : "Bobby",
"GEOMETRY" : {
"type":"Polygon",
"coordinates":[[
[-73.98779153823898,40.718233223261],
[-74.004946447098,40.723575517498],
[-74.006771211624,40.730592217474],
[-73.99010896682698,40.746712376146],
[-73.973135948181,40.73974615047701],
[-73.975120782852,40.736128627654],
[-73.973997695541,40.730787341083],
[-73.983317613602,40.716639396436],
[-73.98779153823898,40.718233223261]
]]},
"FRIEND_POSITON" : {"lon" : -73.992188, "lat" : 40.729359 }
}
This works:
db.friends.find({
"PLAYDATE_RANGE":{
"$geoIntersects":{
"$geometry":{
"type":"Point",
"coordinates":[-73.98652, 40.752044]
}
}
}
})
This does not:
db.friends.find([
{
"PLAYDATE_RANGE":{
"$geoIntersects":{
"$geometry":{
"type":"Point",
"coordinates":[-73.98652, 40.752044]
}
}
}
},
{
"FRIEND_POSITON":{
"$geoNear":{
"near":{
"type":"Point",
"coordinates": [-73.98652, 40.752044]
},
"maxDistance":300
}
}
}
])
Please help me with the query above that does not work.
This requires an aggregate pipeline. As per mogodb doc for $geoNear, You can only use $geoNear as the first stage of a pipeline. The aggregate function has an entry for an additional query which is where the polygon query will be used to narraw down results based on inclusion in the PLAYDATE_RANGE field of the document.
db.friends.aggregate([
{
$geoNear: {
near: { type: "Point", coordinates: [-73.98652, 40.752044] },
maxDistance: 300,
distanceField: "friends.calculated_distance",
query: {
"PLAYDATE_RANGE": {
"$geoIntersects": {
"$geometry": {
"type": "Point",
"coordinates":[-73.98652, 40.752044]
}
}
}
},
spherical: true
}
}
])
P.S. note that only one geospatial index can be used so put it on the FRIEND_POSITION field. If adding a 2sphere index that requires a correctly formed GeoJSON value, specifically,
"FRIEND_POSITION" : { "type" : "Point", "coordinates" : [ -73.992188, 40.729359 ] }
So the document should look like:
{
"_id" : "objid",
"FRIEND_NAME" : "Bobby",
"GEOMETRY" : {
"type": "Polygon",
"coordinates":[[
[-73.98779153823898,40.718233223261],
[-74.004946447098,40.723575517498],
[-74.006771211624,40.730592217474],
[-73.99010896682698,40.746712376146,
[-73.973135948181,40.73974615047701],
[-73.975120782852,40.736128627654],
[-73.973997695541,40.730787341083],
[-73.983317613602,40.716639396436],
[-73.98779153823898,40.718233223261]
]]},
"FRIEND_POSITION" : {
"type" : "Point",
"coordinates" : [ -73.992188, 40.729359 ]
}
}

MongoDb $near and query

I have a collection of documents in structure as below
{ _id: ObjectId("54723e44ec73a702fc979fc9"),
Start: { type: "Point", coordinates: [ -0.15261409999993703, 51.4428311 ] },
End: { type: "Point", coordinates: [ -0.1258020000000215, 51.44695 ] }
}
I am running the following query to try and find documents where the start is 2000 units from a point and the end is 1 unit from a point.
"Start" :
{ "$near" :
{ "$geometry" :
{ "type" : "Point",
"coordinates" : [-0.12580200000002151, 51.44695]
}
},
"$maxDistance" : 2000.0
},
"End" :
{ "$near" :
{ "$geometry" :
{ "type" : "Point",
"coordinates" : [-0.12580200000002151, 51.44695]
}
},
"$maxDistance" : 1.0
}
When I run the query it always returns the documents as if it is doing an or. So where start is x units from a point OR end is x units from a point. So if I run it over the following two documents it returns both where I would only expect the first to be returned.
{ _id: ObjectId("54723e44ec73a702fc979fc9"),
Start: { type: "Point", coordinates: [ -0.15261409999993703, 51.4428311 ] },
End: { type: "Point", coordinates: [ -0.1258020000000215, 51.44695 ] }
}
{ _id: ObjectId("54724f0cec73a70c383a27d4"),
Start: { type: "Point", coordinates: [ -0.15261409999993703, 51.4428311 ] },
End: { type: "Point", coordinates: [ -0.09553900000003068, 51.427025 ] }
}
I am sure I should be able to do this as in
http://blog.mongodb.org/post/50984169045/new-geo-features-in-mongodb-2-4
"Additionally, we can have multiple 2dsphere indexes in the same compound index. This allows queries like: “Find routes with a start location within 50 miles from JFK, and an end location within 100 miles of YYC”."
For clarrification. The query shown above is supposed to be doing and AND query on START location $near point AND END location $near point. But what it actually appears to be doing is START location $near point OR END location $near point.
How do I do and AND query on two $near queries in a single document?