Merge pull request #52 from strongloop/feature/fix-geo-near
Feature/fix geo near
This commit is contained in:
commit
1fcb691e50
39
lib/dao.js
39
lib/dao.js
|
@ -392,14 +392,43 @@ DataAccessObject._coerce = function (where) {
|
||||||
return Boolean(val);
|
return Boolean(val);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
} else if(DataType === Number) {
|
||||||
|
// This fixes a regression in mongodb connector
|
||||||
|
// For numbers, only convert it produces a valid number
|
||||||
|
// LoopBack by default injects a number id. We should fix it based
|
||||||
|
// on the connector's input, for example, MongoDB should use string
|
||||||
|
// while RDBs typically use number
|
||||||
|
DataType = function(val) {
|
||||||
|
var num = Number(val);
|
||||||
|
return !isNaN(num) ? num : val;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!DataType) {
|
if (!DataType) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DataType === geo.GeoPoint) {
|
||||||
|
// Skip the GeoPoint as the near operator breaks the assumption that
|
||||||
|
// an operation has only one property
|
||||||
|
// We should probably fix it based on
|
||||||
|
// http://docs.mongodb.org/manual/reference/operator/query/near/
|
||||||
|
// The other option is to make operators start with $
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var val = where[p];
|
var val = where[p];
|
||||||
|
if(val === null || val === undefined) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
// Check there is an operator
|
// Check there is an operator
|
||||||
var operator = null;
|
var operator = null;
|
||||||
if ('object' === typeof val && Object.keys(val).length === 1) {
|
if ('object' === typeof val) {
|
||||||
|
if (Object.keys(val).length !== 1) {
|
||||||
|
// Skip if there are not only one properties
|
||||||
|
// as the assumption for operators is not true here
|
||||||
|
continue;
|
||||||
|
}
|
||||||
for (var op in operators) {
|
for (var op in operators) {
|
||||||
if (op in val) {
|
if (op in val) {
|
||||||
val = val[op];
|
val = val[op];
|
||||||
|
@ -455,6 +484,11 @@ DataAccessObject.find = function find(params, cb) {
|
||||||
var constr = this;
|
var constr = this;
|
||||||
|
|
||||||
params = params || {};
|
params = params || {};
|
||||||
|
|
||||||
|
if(params.where) {
|
||||||
|
params.where = this._coerce(params.where);
|
||||||
|
}
|
||||||
|
|
||||||
var fields = params.fields;
|
var fields = params.fields;
|
||||||
var near = params && geo.nearFilter(params.where);
|
var near = params && geo.nearFilter(params.where);
|
||||||
var supportsGeo = !!this.getDataSource().connector.buildNearFilter;
|
var supportsGeo = !!this.getDataSource().connector.buildNearFilter;
|
||||||
|
@ -465,9 +499,6 @@ DataAccessObject.find = function find(params, cb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
params = removeUndefined(params);
|
params = removeUndefined(params);
|
||||||
if(params.where) {
|
|
||||||
params.where = this._coerce(params.where);
|
|
||||||
}
|
|
||||||
if(near) {
|
if(near) {
|
||||||
if(supportsGeo) {
|
if(supportsGeo) {
|
||||||
// convert it
|
// convert it
|
||||||
|
|
|
@ -106,8 +106,8 @@ function GeoPoint(data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(typeof data === 'object', 'must provide a lat and lng object when creating a GeoPoint');
|
assert(typeof data === 'object', 'must provide a lat and lng object when creating a GeoPoint');
|
||||||
assert(typeof data.lat === 'number', 'lat must be a number when creating a GeoPoint');
|
assert(typeof data.lat === 'number' && !isNaN(data.lat), 'lat must be a number when creating a GeoPoint');
|
||||||
assert(typeof data.lng === 'number', 'lng must be a number when creating a GeoPoint');
|
assert(typeof data.lng === 'number' && !isNaN(data.lng), 'lng must be a number when creating a GeoPoint');
|
||||||
assert(data.lng <= 180, 'lng must be <= 180');
|
assert(data.lng <= 180, 'lng must be <= 180');
|
||||||
assert(data.lng >= -180, 'lng must be >= -180');
|
assert(data.lng >= -180, 'lng must be >= -180');
|
||||||
assert(data.lat <= 90, 'lat must be <= 90');
|
assert(data.lat <= 90, 'lat must be <= 90');
|
||||||
|
|
|
@ -582,6 +582,7 @@ describe('DataAccessObject', function () {
|
||||||
age: Number,
|
age: Number,
|
||||||
vip: Boolean,
|
vip: Boolean,
|
||||||
date: Date,
|
date: Date,
|
||||||
|
location: 'GeoPoint',
|
||||||
scores: [Number]
|
scores: [Number]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -647,6 +648,34 @@ describe('DataAccessObject', function () {
|
||||||
assert.deepEqual(where, {vip: false});
|
assert.deepEqual(where, {vip: false});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should skip GeoPoint', function () {
|
||||||
|
where = model._coerce({location: {near: {lng: 10, lat: 20}, maxDistance: 20}});
|
||||||
|
assert.deepEqual(where, {location: {near: {lng: 10, lat: 20}, maxDistance: 20}});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should skip null values', function () {
|
||||||
|
where = model._coerce({date: null});
|
||||||
|
assert.deepEqual(where, {date: null});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should skip undefined values', function () {
|
||||||
|
where = model._coerce({date: undefined});
|
||||||
|
assert.deepEqual(where, {date: undefined});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should skip conversion if a simple property produces NaN for numbers',
|
||||||
|
function () {
|
||||||
|
where = model._coerce({age: 'xyz'});
|
||||||
|
assert.deepEqual(where, {age: 'xyz'});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should skip conversion if an array property produces NaN for numbers',
|
||||||
|
function () {
|
||||||
|
where = model._coerce({age: {inq: ['xyz', '12']}});
|
||||||
|
assert.deepEqual(where, {age: {inq: ['xyz', 12]}});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Load models from json', function () {
|
describe('Load models from json', function () {
|
||||||
|
|
Loading…
Reference in New Issue