Mongoose near(...) query on 2dsphere indexed field not returning valid results
javascript, mongodb, mongoose, node.js
Solution
Seems this is a moongoose bug.
Changing the query to use a `GeoJSON` object instead of a coordinate pair, as such:
qry.where('loc').near({
center: {
type: 'Point',
coordinates: search.loc
},
maxDistance: search.distance * 1000
});
results in the following query:
Mongoose: models.find({ loc: { '$near': {
'$maxDistance': 1,
'$geometry': { type: 'Point', coordinates: [ 10, -20 ] } } }
}) { fields: undefined }
The search now succeeds.
The docs explicitly show a query using a coordinate pair:
query.where('loc').near({ center: [10, 10], maxDistance: 5 });
However, it looks like this doesn't work, and the example should be:
query.where('loc').near({ center: { coordinates: [10, 10], type: 'Point' }, maxDistance: 5 });
Problem
I am unable to query a mongodb database using mongoose's `qry.where().near()` syntax. I have a Schema with coordinates stored as an array, indexed as `2dsphere`: ``` loc : { type: [Number], index: '2dsphere' } ``` I am running a mongoose query using `.where().near()`: ``` qry.where('loc').near({ center: search.loc, maxDistance: search.distance * 1000 }); ``` I have enabled `mongoose.set('debug', true)`, and can see the resulting debug: Inserting 2 documents in the collection with coordinates `[ 10, -20 ]`: ``` Mongoose: models.insert({ _id: ..., loc: [ 10, -20 ], type: 'apple' }) {} Mongoose: models.insert({ _id: ..., loc: [ 10, -20 ], type: 'orange' }) {} ``` Searching for documents near coordinates `[ 10, -20 ]`: ``` Mongoose: models.find({ loc: { '$near': [ 10, -20 ], '$maxDistance': 1000 } }) ``` The query returns no results. I have proved the documents are in the database by searching on `type`. Its the geospatial query I can't get to work. I am using `mongodb v2.6.1` and `mongoose v3.8.8` Full working example below: Schema: (model.js) ``` var mongoose = require('mongoose'), Schema = mongoose.Schema; var ModelSchema = new Schema({ type : { type: String, index: true }, loc : { type: [Number], index: '2dsphere' } }); ModelSchema.index({type: 1, loc: 1}); ModelSchema.statics.search = function(search, cb) { var qry = this.find(); if (search.types) { qry.where('type').in(search.types); } if (search.loc) { qry.where('loc').near({ center: search.loc, maxDistance: search.distance * 1000 }); } qry.exec(cb); }; ``` Mocha test: (test.ts) ``` var q = require('node-promise'), should = require('should'), mongoose = require('mongoose'); mongoose.connect('mongodb://localhost/my-test'); var Model = require('./model'); describe('My Model', function() { before(function(done) { mongoose.set('debug', true); Model.remove().exec(function() { var create = function(promises, body) { var p = new q.Promise(); var m = new Model(body); m.save(function(err) { if (err) { console.log(err); p.reject(); } else { p.resolve(); } }); promises.push(p); }; var promises = []; create(promises, { type: 'apple', loc: [ 10, -20 ] }); create(promises, { type: 'orange', loc: [ 10, -20 ] }); create(promises, { type: 'apple', loc: [ 15, 10 ] }); create(promises, { type: 'orange', loc: [ 15, 10 ] }); q.all(promises).then(function() { done(); }) }); }); it('should find all', function(done) { Model.search({}, function(err, items) { items.should.have.length(4); done(); }); }); it('should find apples', function(done) { Model.search({types: ['apple']}, function(err, items) { items.should.have.length(2); done(); }); }); // this test fails it('should find coords', function(done) { Model.search({loc: [ 10, -20 ], distance: 1}, function(err, items) { items.should.have.length(2); done(); }); }); }); ``` package.json: ``` { "name": "test", "version": "0.0.0", "dependencies": { "mongoose": "~3.8.8" }, "devDependencies": { "should": "~2.1.0", "node-promise": "0.5.10" } } ``` Run through mocha: ``` sudo npm install -g mocha npm install mocha ./test.js ```