From 650e88d79fd8214e9830fd3b1c2cb343b9d2aa14 Mon Sep 17 00:00:00 2001 From: Harish Krishna Date: Thu, 22 Jan 2015 16:42:27 -0500 Subject: [PATCH] making geo bias optional - first pass with all tests passing --- query/search.js | 55 ++++++++++++++++++++++++++++++---- query/suggest.js | 5 +++- sanitiser/_geo.js | 36 +++++++++++----------- test/unit/sanitiser/coarse.js | 3 +- test/unit/sanitiser/suggest.js | 9 +++--- 5 files changed, 77 insertions(+), 31 deletions(-) diff --git a/query/search.js b/query/search.js index 2dd99e81..2805a1fa 100644 --- a/query/search.js +++ b/query/search.js @@ -4,16 +4,59 @@ var logger = require('../src/logger'), function generate( params ){ - var centroid = { - lat: params.lat, - lon: params.lon + var query = { + 'query': { + 'filtered': { + 'query': { + 'match_all': {} + }, + 'filter' : { + 'bool': { + 'must': [] + } + } + } + }, + 'size': params.size }; - var query = queries.distance( centroid, { size: params.size } ); - + // TODO: DRY (the following lines are repeated here and in geopipes-elasticsearchbackend) + // query/geo_bbox - cleanup necessary #techdebt if (params.bbox) { - query = queries.bbox ( centroid, { size: params.size, bbox: params.bbox } ); + var options = { + top : Number( params.bbox.top ).toFixed(2), // @note: make filter cachable + right : Number( params.bbox.right ).toFixed(2), // precision max ~1.113km off + bottom: Number( params.bbox.bottom ).toFixed(2), + left : Number( params.bbox.left ).toFixed(2), + size: params.size || 1, + field: params.field || 'center_point' + }; + var filter = { + 'geo_bounding_box' : { + '_cache': true // Speed up duplicate queries. Memory impact? + } + }; + + filter.geo_bounding_box[ options.field ] = { + 'top' : options.top, + 'right' : options.right, + 'bottom': options.bottom, + 'left' : options.left, + }; + query.query.filtered.filter.bool.must.push( filter ); + } + + if ( params.lat && params.lon ){ + var centroid = { + lat: params.lat, + lon: params.lon + }; + query = queries.distance( centroid, { size: params.size } ); + if (params.bbox) { + query = queries.bbox ( centroid, { size: params.size, bbox: params.bbox } ); + } } + // add search condition to distance query query.query.filtered.query = { diff --git a/query/suggest.js b/query/suggest.js index a61f9582..7d19cc19 100644 --- a/query/suggest.js +++ b/query/suggest.js @@ -36,7 +36,7 @@ function generate( params, query_mixer, fuzziness ){ 'context': { 'dataset': layers || this.params.layers, 'location': { - 'value': [ this.params.lon, this.params.lat ], + 'value': [ ], 'precision': precision || this.get_precision() } }, @@ -45,6 +45,9 @@ function generate( params, query_mixer, fuzziness ){ } } }; + if (!isNaN(this.params.lon) && !isNaN(this.params.lat)) { + this.cmd[name].completion.context.location.value = [ this.params.lon, this.params.lat ]; + } }; var cmd = new CmdGenerator(params); diff --git a/sanitiser/_geo.js b/sanitiser/_geo.js index 5e8baa64..0b874837 100644 --- a/sanitiser/_geo.js +++ b/sanitiser/_geo.js @@ -18,32 +18,34 @@ function sanitize( req ){ }; // lat - var lat = parseFloat( params.lat, 10 ); - if( is_invalid_lat(lat) ){ - return { - 'error': true, - 'message': 'invalid param \'lat\': must be >-90 and <90' - }; + if (!isNaN(params.lat)) { + var lat = parseFloat( params.lat, 10 ); + if( is_invalid_lat(lat) ){ + return { + 'error': true, + 'message': 'invalid param \'lat\': must be >-90 and <90' + }; + } + clean.lat = lat; } - clean.lat = lat; // lon - var lon = parseFloat( params.lon, 10 ); - if( is_invalid_lon(lon) ){ - return { - 'error': true, - 'message': 'invalid param \'lon\': must be >-180 and <180' - }; + if (!isNaN(params.lon)) { + var lon = parseFloat( params.lon, 10 ); + if( is_invalid_lon(lon) ){ + return { + 'error': true, + 'message': 'invalid param \'lon\': must be >-180 and <180' + }; + } + clean.lon = lon; } - clean.lon = lon; // zoom level var zoom = parseInt( params.zoom, 10 ); if( !isNaN( zoom ) ){ clean.zoom = Math.min( Math.max( zoom, 1 ), 18 ); // max - } else { - clean.zoom = 10; // default - } + } // bbox // bbox = bottom_left lat, bottom_left lon, top_right lat, top_right lon diff --git a/test/unit/sanitiser/coarse.js b/test/unit/sanitiser/coarse.js index f626141b..f389b423 100644 --- a/test/unit/sanitiser/coarse.js +++ b/test/unit/sanitiser/coarse.js @@ -53,8 +53,7 @@ module.exports.tests.middleware_success = function(test, common) { size: 10, layers: [ 'admin0', 'admin1', 'admin2', 'neighborhood' ], lat: 0, - lon: 0, - zoom: 10 + lon: 0 }; t.equal(message, undefined, 'no error message set'); t.deepEqual(req.clean, defaultClean); diff --git a/test/unit/sanitiser/suggest.js b/test/unit/sanitiser/suggest.js index dc68a6c0..6ea903e5 100644 --- a/test/unit/sanitiser/suggest.js +++ b/test/unit/sanitiser/suggest.js @@ -4,12 +4,11 @@ var suggest = require('../../../sanitiser/suggest'), middleware = suggest.middleware, defaultError = 'invalid param \'input\': text length, must be >0', defaultClean = { input: 'test', - lat: 0, + lat:0, layers: [ 'geoname', 'osmnode', 'osmway', 'admin0', 'admin1', 'admin2', 'neighborhood', 'osmaddress', 'openaddresses' ], - lon: 0, - size: 10, - zoom: 10 + lon: 0, + size: 10 }, sanitize = function(query, cb) { _sanitize({'query':query}, cb); }; @@ -173,7 +172,7 @@ module.exports.tests.sanitize_bbox = function(test, common) { module.exports.tests.sanitize_zoom = function(test, common) { test('invalid zoom value', function(t) { sanitize({ zoom: 'a', input: 'test', lat: 0, lon: 0 }, function( err, clean ){ - t.equal(clean.zoom, 10, 'default zoom set'); + t.equal(clean.zoom, undefined, 'zoom not set'); t.end(); }); });