yprez
yprez

Reputation: 15154

Calculate distance in MongoDB map-reduce

I have a MongoDB collection with a geo index:

> db.coll.getIndexes()
[
    // ...
    {
        "v" : 1,
        "key" : {
            "location" : "2dsphere"
        },
        "ns" : "test.coll",
        "dropDups" : false,
        "name" : "location_2dsphere",
        "background" : false
    }
]

db.coll.findOne({location: {'$exists': true}}, {'location': 1})
{
    "_id" : ObjectId("52cd72ae2ac170aa3eaace6e"),
    "location" : [
        55.4545177559,
        11.5767419669
    ]
}

On which I'm running map reduce, which looks something like this:

var map = function() {
     var value = 0;

     // ... various calculations on the value here

     var distance = 0; // < This is the problematic part
     if (distance < 1000) {
         val += distance;  // for example
     }

     emit(this._id, value)
}
var reduce = function(id, val) {
    return {id: val}
}

db.coll.mapReduce(map, reduce, {out: {inline: 1}})

Is there a way to calculate the distance between location and point X, in the map function?

I'm looking for something like $geoNear, but somehow combined with the map-reduce.

For example:

db.runCommand({geoNear: "coll", near: [-74, 40.74], spherical: true})

Returns the distance for each document. But I can't find a way to combine it with the map-reduce command.

Upvotes: 3

Views: 654

Answers (2)

Norman H
Norman H

Reputation: 2262

I know this is a late addition but for other folks coming here it might be good to know about a suite of Javascript libraries that are available to do geo related functions.

https://github.com/manuelbieh/Geolib

Upvotes: 1

astroanu
astroanu

Reputation: 4001

The Great Circle Formula is the way to go http://en.wikipedia.org/wiki/Great-circle_distance

I ran in to a similar problem with mongo and js. And came up with this function. Hope it helps.

function find(point, latlng, radius){
       var dist = parseInt(radius) * 0.868976 / 60; // convert miles to rad

    if((point[0] <= latlng[0] + dist && point[1] >= latlng[1]- dist) 
    && (point[0] <= latlng[0]+ dist && point[1] >= latlng[1]- dist)){

        dx = latlng[0] - point[0];
        dy = latlng[1] - point[1];
        dx *= dx;
        dy *= dy;
        ds = dx + dy;
        rs = dist * dist;
        is =  ds <= rs;

        return is;
    }
}

Im calling this like this:

find([-79,5], [40,20], 5);

Upvotes: 5

Related Questions