23

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.

Blakes Seven
  • 49,422
  • 14
  • 129
  • 135
work_in_progress
  • 747
  • 1
  • 10
  • 27

4 Answers4

39

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".

Renish Gotecha
  • 2,232
  • 22
  • 21
Blakes Seven
  • 49,422
  • 14
  • 129
  • 135
  • Thanks a lot, it is working perfectly. Curious to know why did you multiply it by 1609? – work_in_progress Nov 23 '15 at 06:14
  • 2
    @SiMemon Because there are 1609 meters in a mile, and vice/versa on the distanceMultiplier. The 3963 number you were using is the conversion of "radians" to miles, which when used with GeoJSON point coordinates would be incorrect. Radians are only used with both storage and query are using "legacy coordinate pairs". – Blakes Seven Nov 23 '15 at 06:18
  • Can we find distance from queried point to multiple geopoints in same query instead of one? – Dileep Paul Oct 01 '18 at 15:15
  • Could this determine if two circles intersect? That is, suppose I have a collection which contains a latitude and longitude, as well as a radius. Since GeoJSON does not support circles, could I write a query to determine the distance between two points, and then check if that distance is less than the sum of both radii? Would that work and would it be performant? Thanks. –  Apr 27 '19 at 22:42
6

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.

0

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.

Utkarsh Singh
  • 59
  • 1
  • 2
0

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()
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Oct 17 '22 at 22:47