geoNear command, here's a possible implementation

186 views
Skip to first unread message

Matteo Muratori

unread,
Mar 28, 2011, 11:17:03 AM3/28/11
to node-mongodb-native

As far as I know, the geoNear command (supported by latest MongoDB
versions) has not been already added to the great node-mongodb-native
driver.
After writing to Christian Amor Kvalheim (the node-mongodb-native
driver author), I've decided to post my geoNear command
implementation, because he never answered me about a possible
integration.
So here's my geoNear code, wishing that some other node-mongodb-native
developer could integrate it in the official branch.
The code could be (should be) improved in order to use the Cursor
class for the geoNear results; at the moment returned values are
stored in memory all together.

/**
* Execute the geoNear command; this command has the added benefit
(respect to the find command) of returning the distance of each item
from the specified point in the results.
*
* @param options Options can be:
* near: [x, y]
* spherical: true/false
* maxDistance: number, it scales the distance returned as 'dis' in
the result documents
* distanceMultiplier: number, all distances results (i.e. .dis
field) are scaled by this factor
* num: limit number of returned documents
* query: additional query filter
*
* @param callback {function(Error, Array<Object>)} This will be called
after executing this method successfully.
* The first paramter will contain the Error object if an error
occured, or null otherwise.
* The second paramter will contain an array of documents: each
document has the following format:
* {
* 'dis': the distance (with maxDistance already applied)
* 'obj': the real database document
* }
*
* Example: collection.geoNear({ 'near': [44.6, 12.71], 'spherical':
true, 'maxDistance': 10.2, 'distanceMultiplier': 6378160.0, 'num': 5,
'query': { 'type': 'museum' } }, function(err, docs) { ... });
*
*/

var QueryCommand = require('mongodb').QueryCommand,
DbCommand = require('mongodb').DbCommand,
Collection = require('mongodb').Collection;

Collection.prototype.geoNear = function(options, callback) {

var command;
var selector = {
'geoNear': this.collectionName
};

callback = callback || function(err, docs) {};

if (options) {
// near
if (options.near && options.near instanceof Array &&
options.near.length > 1)
selector.near = [options.near[0], options.near[1]];
// spherical
options.spherical ? selector.spherical = true :
selector.spherical = false;
// maxDistance
if (options.maxDistance && typeof options.maxDistance ==
'number')
selector.maxDistance = options.maxDistance;
// distanceMultiplier
if (options.distanceMultiplier && typeof
options.distanceMultiplier == 'number')
selector.distanceMultiplier = options.distanceMultiplier;
// num
if (options.num && typeof options.num == 'number')
selector.num = options.num;
// query
if (options.query)
selector.query = options.query;
}

// build the db command
command = new DbCommand(this.db, this.db.databaseName + '.' +
DbCommand.SYSTEM_COMMAND_COLLECTION,
QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, selector, null);
// execute the command
this.db.executeCommand(command, function(err, result) {
if (err == null && result.documents[0].ok == 1)
// pass documents to the callback
callback(null, result.documents[0].results);
else
// report the error
err != null ? callback(err, null) : callback(new
Error(result.documents[0].errmsg), null);
});
}

Have fun!
Matteo.

Andrew Hodel

unread,
Mar 28, 2011, 11:22:39 AM3/28/11
to node-mong...@googlegroups.com
Fork it on github.

Pau

unread,
Mar 28, 2011, 11:23:43 AM3/28/11
to node-mong...@googlegroups.com, Matteo Muratori
Just open a Pull request with some integration tests and I'm sure Christian will merge it.
Reply all
Reply to author
Forward
0 new messages