From 6856ff725439f8680d14c23f96e2d7d896de748e Mon Sep 17 00:00:00 2001 From: Ritchie Martori Date: Mon, 24 Jun 2013 15:21:59 -0700 Subject: [PATCH] Add geo filtering for memory adapter --- lib/adapters/memory.js | 33 +++++++++++++++++++++++++- lib/geo.js | 53 ++++++++++++++++++++++++++++++++++++++++++ lib/model-builder.js | 3 +++ 3 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 lib/geo.js diff --git a/lib/adapters/memory.js b/lib/adapters/memory.js index 7982ad0f..17b614bd 100644 --- a/lib/adapters/memory.js +++ b/lib/adapters/memory.js @@ -1,3 +1,5 @@ +var geo = require('../geo'); + exports.initialize = function initializeSchema(schema, callback) { schema.adapter = new Memory(); schema.adapter.connect(callback); @@ -108,9 +110,10 @@ Memory.prototype.all = function all(model, filter, callback) { var nodes = Object.keys(this.cache[model]).map(function (key) { return this.fromDb(model, this.cache[model][key]); }.bind(this)); + var isGeo = false; + if (filter) { - // do we need some sorting? if (filter.order) { var props = this._models[model].properties; @@ -129,6 +132,13 @@ Memory.prototype.all = function all(model, filter, callback) { }); nodes = nodes.sort(sorting.bind(orders)); } + + var nearFilter = nearFilter(filter.where); + + // geo sorting + if(nearFilter) { + nodes = geo.filter(nodes, nearFilter); + } // do we need some filtration? if (filter.where) { @@ -160,6 +170,26 @@ Memory.prototype.all = function all(model, filter, callback) { } return 0; } + + function nearFilter(where) { + var result = false; + + if(where && typeof where === 'object') { + Object.keys(where).forEach(function (key) { + var ex = where[key]; + + if(ex && ex.near) { + result = { + near: ex.near, + maxDistance: ex.maxDistance, + key: key + }; + } + }); + } + + return result; + } }; function applyFilter(filter) { @@ -191,6 +221,7 @@ function applyFilter(filter) { } return false; } + if(isNum(example.gt) && example.gt < value) return true; if(isNum(example.gte) && example.gte <= value) return true; if(isNum(example.lt) && example.lt > value) return true; diff --git a/lib/geo.js b/lib/geo.js new file mode 100644 index 00000000..6ef18d09 --- /dev/null +++ b/lib/geo.js @@ -0,0 +1,53 @@ +exports.filter = function (arr, filter) { + var origin = filter.near; + var max = filter.maxDistance > 0 ? filter.maxDistance : false; + var key = filter.key; + + // create distance index + var distances = {}; + var result = []; + + arr.forEach(function (obj) { + var loc = obj[key]; + + // filter out objects without locations + if(!loc) return; + if(typeof loc.lat !== 'number') return; + if(typeof loc.long !== 'number') return; + + var d = distanceBetween(origin, loc); + + if(max && d > max) { + // dont add + } else { + distances[obj.id] = d; + result.push(obj); + } + }); + + return result.sort(function (objA, objB) { + var a = objB[key]; + var b = objB[key]; + + if(a && b) { + var da = distances[objA.id]; + var db = distances[objB.id]; + + if(db === da) return 0; + return da > db ? -1 : 1; + } else { + return 0; + } + }); +} + +var distanceBetween = exports.distanceBetween = function distanceBetween(a, b) { + var xs = 0; + var ys = 0; + xs = a.lat - b.lat; + xs = xs * xs; + ys = a.long - b.long; + ys = ys * ys; + + return Math.sqrt( xs + ys ); +} \ No newline at end of file diff --git a/lib/model-builder.js b/lib/model-builder.js index 940f99ca..51b8e534 100644 --- a/lib/model-builder.js +++ b/lib/model-builder.js @@ -215,6 +215,9 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett if (value === null || value === undefined) { this.__data[attr] = value; } else { + if(attr === 'geo') { + debugger; + } this.__data[attr] = DataType(value); } }