Skip to content

Commit

Permalink
refactor(collection): remove geoNear command helper
Browse files Browse the repository at this point in the history
  • Loading branch information
mbroadst committed Dec 20, 2017
1 parent 3f69250 commit 44373f3
Show file tree
Hide file tree
Showing 8 changed files with 10 additions and 446 deletions.
6 changes: 6 additions & 0 deletions CHANGES_3.0.0.md
Expand Up @@ -202,6 +202,12 @@ testCollection.updateOne({_id: 'test'}, {});

Wherever it occurs, the option `keepAlive` has been changed. `keepAlive` is now a boolean that enables/disables `keepAlive`, while `keepAliveInitialDelay` specifies how long to wait before initiating keepAlive. This brings the API in line with [NodeJS's socket api](https://nodejs.org/dist/latest-v9.x/docs/api/all.html#net_socket_setkeepalive_enable_initialdelay)

### `geoNear` command helper

The functionality of the geoNear command is duplicated elsewhere in the language, in the `$near`/`$nearSphere` query operators on unsharded collections, and in the `$geoNear` aggregation stage on all collections. Maintaining this command increases our test surface, and creates additional work when adding features that must be supported on all read commands. As a result, the command will be fully
removed in the MongoDB 4.0 release, and we are choosing to remove it in this
major release of the node driver.

### Tests

We have updated all of the tests to use [Mocha](https://mochajs.org) and a new test runner, [`mongodb-test-runner`](https://github.com/mongodb-js/mongodb-test-runner), which
Expand Down
70 changes: 0 additions & 70 deletions lib/collection.js
Expand Up @@ -2630,76 +2630,6 @@ var parallelCollectionScan = function(self, options, callback) {

define.classMethod('parallelCollectionScan', { callback: true, promise: true });

/**
* Execute the geoNear command to search for items in the collection
*
* @method
* @param {number} x Point to search on the x axis, ensure the indexes are ordered in the same order.
* @param {number} y Point to search on the y axis, ensure the indexes are ordered in the same order.
* @param {object} [options=null] Optional settings.
* @param {(ReadPreference|string)} [options.readPreference=null] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
* @param {number} [options.num=null] Max number of results to return.
* @param {number} [options.minDistance=null] Include results starting at minDistance from a point (2.6 or higher)
* @param {number} [options.maxDistance=null] Include results up to maxDistance from the point.
* @param {number} [options.distanceMultiplier=null] Include a value to multiply the distances with allowing for range conversions.
* @param {object} [options.query=null] Filter the results by a query.
* @param {boolean} [options.spherical=false] Perform query using a spherical model.
* @param {boolean} [options.uniqueDocs=false] The closest location in a document to the center of the search region will always be returned MongoDB > 2.X.
* @param {boolean} [options.includeLocs=false] Include the location data fields in the top level of the results MongoDB > 2.X.
* @param {ClientSession} [options.session] optional session to use for this operation
* @param {Collection~resultCallback} [callback] The command result callback
* @return {Promise} returns Promise if no callback passed
*/
Collection.prototype.geoNear = function(x, y, options, callback) {
var point = typeof x === 'object' && x,
args = Array.prototype.slice.call(arguments, point ? 1 : 2);
callback = typeof args[args.length - 1] === 'function' ? args.pop() : undefined;
options = args.length ? args.shift() || {} : {};

return executeOperation(this.s.topology, geoNear, [this, x, y, point, options, callback]);
};

var geoNear = function(self, x, y, point, options, callback) {
// Build command object
var commandObject = {
geoNear: self.s.name,
near: point || [x, y]
};

options = shallowClone(options);
// Ensure we have the right read preference inheritance
options = getReadPreference(self, options, self.s.db, self);

// Exclude readPreference and existing options to prevent user from
// shooting themselves in the foot
var exclude = {
readPreference: true,
geoNear: true,
near: true,
session: true
};

// Filter out any excluded objects
commandObject = decorateCommand(commandObject, options, exclude);

// Do we have a readConcern specified
decorateWithReadConcern(commandObject, self, options);

// Have we specified collation
decorateWithCollation(commandObject, self, options);

// Execute the command
self.s.db.command(commandObject, options, function(err, res) {
if (err) return handleCallback(callback, err);
if (res.err || res.errmsg) return handleCallback(callback, toError(res));
// should we only be returning res.results here? Not sure if the user
// should see the other return information
handleCallback(callback, null, res);
});
};

define.classMethod('geoNear', { callback: true, promise: true });

/**
* Execute a geo search using a geo haystack index on a collection.
*
Expand Down
50 changes: 0 additions & 50 deletions test/functional/collations_tests.js
Expand Up @@ -217,56 +217,6 @@ describe('Collation', function() {
}
});

it('Successfully pass through collation to geoNear command', {
metadata: { requires: { generators: true, topology: 'single' } },

test: function(done) {
var configuration = this.configuration,
MongoClient = configuration.require.MongoClient;

// Primary server states
var primary = [Object.assign({}, defaultFields)];

co(function*() {
const singleServer = yield mock.createServer();

// Primary state machine
singleServer.setMessageHandler(request => {
var doc = request.document;
if (doc.ismaster) {
request.reply(primary[0]);
} else if (doc.geoNear) {
commandResult = doc;
request.reply({ ok: 1 });
} else if (doc.endSessions) {
request.reply({ ok: 1 });
}
});

var commandResult = null;

// Connect to the mocks
MongoClient.connect(`mongodb://${singleServer.uri()}/test`, function(err, client) {
test.equal(null, err);
var db = client.db(configuration.db);

// Simple findAndModify command returning the new document
db
.collection('test')
.geoNear(50, 50, { query: { a: 1 }, num: 1, collation: { caseLevel: true } }, function(
err
) {
test.equal(null, err);
test.deepEqual({ caseLevel: true }, commandResult.collation);

client.close();
done();
});
});
});
}
});

it('Successfully pass through collation to group command', {
metadata: { requires: { generators: true, topology: 'single' } },

Expand Down
60 changes: 1 addition & 59 deletions test/functional/operation_example_tests.js
Expand Up @@ -1703,64 +1703,6 @@ describe('Operation Examples', function() {
}
});

/**
* Example of a simple geoNear query across some documents
*
* @example-class Collection
* @example-method geoNear
* @ignore
*/
it('shouldCorrectlyPerformSimpleGeoNearCommand', {
metadata: {
requires: { topology: ['single', 'replicaset', 'sharded', 'ssl', 'heap', 'wiredtiger'] }
},

// The actual test we wish to run
test: function(done) {
var configuration = this.configuration;
var client = configuration.newClient(configuration.writeConcernMax(), { poolSize: 1 });
client.connect(function(err, client) {
// LINE var MongoClient = require('mongodb').MongoClient,
// LINE test = require('assert');
// LINE MongoClient.connect('mongodb://localhost:27017/test', function(err, client) {
// LINE var db = client.db('test);
// REPLACE configuration.writeConcernMax() WITH {w:1}
// REMOVE-LINE restartAndDone
// REMOVE-LINE done();
// REMOVE-LINE var db = client.db(configuration.db);
// BEGIN
var db = client.db(configuration.db);
// Fetch the collection
var collection = db.collection('simple_geo_near_command');

// Add a location based index
collection.ensureIndex({ loc: '2d' }, function(err, result) {
test.ok(result);
test.equal(null, err);

// Save a new location tagged document
collection.insertMany(
[{ a: 1, loc: [50, 30] }, { a: 1, loc: [30, 50] }],
configuration.writeConcernMax(),
function(err, result) {
test.ok(result);
test.equal(null, err);

// Use geoNear command to find document
collection.geoNear(50, 50, { query: { a: 1 }, num: 1 }, function(err, docs) {
test.equal(1, docs.results.length);

client.close();
done();
});
}
);
});
});
// END
}
});

/**
* Example of a simple geoHaystackSearch query across some documents
*
Expand Down Expand Up @@ -1805,7 +1747,7 @@ describe('Operation Examples', function() {
test.ok(result);
test.equal(null, err);

// Use geoNear command to find document
// Use geoHaystackSearch command to find document
collection.geoHaystackSearch(
50,
50,
Expand Down
56 changes: 1 addition & 55 deletions test/functional/operation_generators_example_tests.js
Expand Up @@ -1018,60 +1018,6 @@ describe('Operation (Generators)', function() {
}
});

/**
* Example of a simple geoNear query across some documents using a Generator and the co module.
*
* @example-class Collection
* @example-method geoNear
* @ignore
*/
it('shouldCorrectlyPerformSimpleGeoNearCommandWithGenerators', {
metadata: { requires: { generators: true, topology: ['single'] } },

// The actual test we wish to run
test: function() {
var configuration = this.configuration;
var co = require('co');

return co(function*() {
// Connect
var client = yield configuration
.newClient(configuration.writeConcernMax(), { poolSize: 1 })
.connect();
var db = client.db(configuration.db);
// LINE var MongoClient = require('mongodb').MongoClient,
// LINE co = require('co');
// LINE test = require('assert');
// LINE
// LINE co(function*() {
// LINE var client = yield MongoClient.connect('mongodb://localhost:27017/test');
// LINE var db = client.db('test');
// REPLACE configuration.writeConcernMax() WITH {w:1}
// BEGIN

// Fetch the collection
var collection = db.collection('simple_geo_near_command_with_generators');

// Add a location based index
yield collection.ensureIndex({ loc: '2d' });

// Save a new location tagged document
yield collection.insertMany(
[{ a: 1, loc: [50, 30] }, { a: 1, loc: [30, 50] }],
configuration.writeConcernMax()
);

// Use geoNear command to find document
var docs = yield collection.geoNear(50, 50, { query: { a: 1 }, num: 1 });
test.equal(1, docs.results.length);

// Close db
client.close();
});
// END
}
});

/**
* Example of a simple geoHaystackSearch query across some documents using a Generator and the co module.
*
Expand Down Expand Up @@ -1115,7 +1061,7 @@ describe('Operation (Generators)', function() {
configuration.writeConcernMax()
);

// Use geoNear command to find document
// Use geoHaystackSearch command to find document
var docs = yield collection.geoHaystackSearch(50, 50, {
search: { a: 1 },
limit: 1,
Expand Down
57 changes: 1 addition & 56 deletions test/functional/operation_promises_example_tests.js
Expand Up @@ -1055,61 +1055,6 @@ describe('Operation (Promises)', function() {
}
});

/**
* Example of a simple geoNear query across some documents using a Promise.
*
* @example-class Collection
* @example-method geoNear
* @ignore
*/
it('shouldCorrectlyPerformSimpleGeoNearCommandWithPromises', {
metadata: { requires: { promises: true, topology: ['single'] } },

// The actual test we wish to run
test: function() {
var configuration = this.configuration;
var client = configuration.newClient(configuration.writeConcernMax(), { poolSize: 1 });

return client.connect().then(function(client) {
var db = client.db(configuration.db);
// LINE var MongoClient = require('mongodb').MongoClient,
// LINE test = require('assert');
// LINE MongoClient.connect('mongodb://localhost:27017/test', function(err, client) {
// LINE var db = client.db('test);
// REPLACE configuration.writeConcernMax() WITH {w:1}
// REMOVE-LINE done();
// BEGIN

// Fetch the collection
var collection = db.collection('simple_geo_near_command_with_promise');

// Add a location based index
return collection
.ensureIndex({ loc: '2d' })
.then(function(result) {
test.ok(result);

// Save a new location tagged document
return collection.insertMany(
[{ a: 1, loc: [50, 30] }, { a: 1, loc: [30, 50] }],
configuration.writeConcernMax()
);
})
.then(function(result) {
test.ok(result);

// Use geoNear command to find document
return collection.geoNear(50, 50, { query: { a: 1 }, num: 1 });
})
.then(function(docs) {
test.equal(1, docs.results.length);
client.close();
});
});
// END
}
});

/**
* Example of a simple geoHaystackSearch query across some documents using a Promise.
*
Expand Down Expand Up @@ -1153,7 +1098,7 @@ describe('Operation (Promises)', function() {
.then(function(result) {
test.ok(result);

// Use geoNear command to find document
// Use geoHaystackSearch command to find document
return collection.geoHaystackSearch(50, 50, {
search: { a: 1 },
limit: 1,
Expand Down

0 comments on commit 44373f3

Please sign in to comment.