Browse Source

consolidating suggest_poi and suggest_admin into one suggest endpoint. fixing tests (more tests to come)

pull/27/head
Harish Krishna 10 years ago
parent
commit
f1d13c1337
  1. 4
      app.js
  2. 120
      controller/suggest.js
  3. 50
      controller/suggest_admin.js
  4. 46
      controller/suggest_poi.js
  5. 0
      query/suggest.js
  6. 29
      query/suggest_admin.js
  7. 15
      test/unit/controller/suggest.js
  8. 10
      test/unit/mock/backend.js
  9. 2
      test/unit/query/suggest.js

4
app.js

@ -22,8 +22,6 @@ var controllers = {};
controllers.index = require('./controller/index'); controllers.index = require('./controller/index');
controllers.doc = require('./controller/doc'); controllers.doc = require('./controller/doc');
controllers.suggest = require('./controller/suggest'); controllers.suggest = require('./controller/suggest');
controllers.suggest_poi = require('./controller/suggest_poi');
controllers.suggest_admin = require('./controller/suggest_admin');
controllers.search = require('./controller/search'); controllers.search = require('./controller/search');
/** ----------------------- routes ----------------------- **/ /** ----------------------- routes ----------------------- **/
@ -36,8 +34,6 @@ app.get( '/doc', sanitisers.doc.middleware, controllers.doc() );
// suggest API // suggest API
app.get( '/suggest', sanitisers.suggest.middleware, controllers.suggest() ); app.get( '/suggest', sanitisers.suggest.middleware, controllers.suggest() );
app.get( '/suggest/poi', sanitisers.suggest.middleware, controllers.suggest_poi() );
app.get( '/suggest/admin', sanitisers.suggest.middleware, controllers.suggest_admin() );
// search API // search API
app.get( '/search', sanitisers.search.middleware, controllers.search() ); app.get( '/search', sanitisers.search.middleware, controllers.search() );

120
controller/suggest.js

@ -4,17 +4,19 @@ var async = require('async');
function setup( backend, query ){ function setup( backend, query ){
function controller( req, res, next ){ // allow overriding of dependencies
backend = backend || require('../src/backend');
query = query || require('../query/suggest');
// combine the 2 queries function controller( req, res, next ){
// allow overriding of dependencies
backend = backend || require('../src/backend');
var query_admin = require('../query/suggest_admin');
var query_poi = require('../query/suggest_poi');
var cmd = { var cmd = {
index: 'pelias' index: 'pelias',
body: query( req.clean )
}; };
var SIZE = req.clean.size || 10;
var query_backend = function(cmd, callback) { var query_backend = function(cmd, callback) {
// query backend // query backend
backend().client.suggest( cmd, function( err, data ){ backend().client.suggest( cmd, function( err, data ){
@ -55,57 +57,67 @@ function setup( backend, query ){
return res.status(200).json( geojson ); return res.status(200).json( geojson );
}; };
var async_query; if (req.clean.input) {
var async_query;
if (req.clean.input.length < 4 && isNaN(parseInt(req.clean.input, 10))) {
async_query = { // admin only
a: function(callback){ req.admin = {};
cmd.body = query_admin( req.clean, 3 ); for (k in req.clean) { req.admin[k] = req.clean[k] }
query_backend(cmd, callback); req.admin.layers = ['admin0','admin1','admin2'];
},
b: function(callback){ if (req.clean.input.length < 4 && isNaN(parseInt(req.clean.input, 10))) {
cmd.body = query_admin( req.clean, 1 ); async_query = {
query_backend(cmd, callback); a: function(callback){
}, cmd.body = query( req.admin, 3 );
c: function(callback) { query_backend(cmd, callback);
cmd.body = query_poi( req.clean, 3 ); },
query_backend(cmd, callback); b: function(callback){
cmd.body = query( req.admin, 1 );
query_backend(cmd, callback);
},
c: function(callback) {
cmd.body = query( req.clean, 3 );
query_backend(cmd, callback);
}
} }
} } else {
} else { async_query = {
async_query = { a: function(callback){
a: function(callback){ cmd.body = query( req.clean, 5);
cmd.body = query_poi( req.clean, 5); query_backend(cmd, callback);
query_backend(cmd, callback); },
}, b: function(callback){
b: function(callback){ cmd.body = query( req.clean, 3);
cmd.body = query_poi( req.clean, 3); query_backend(cmd, callback);
query_backend(cmd, callback); },
}, c: function(callback){
c: function(callback){ cmd.body = query( req.clean, 1 );
cmd.body = query_poi( req.clean, 1 ); query_backend(cmd, callback);
query_backend(cmd, callback); },
}, d: function(callback){
d: function(callback){ cmd.body = query( req.admin );
cmd.body = query_admin( req.clean ); query_backend(cmd, callback);
query_backend(cmd, callback); }
} }
} }
}
async.parallel(async_query, function(err, results) {
var splice_length = parseInt((req.clean.size / Object.keys(results).length), 10);
// results is equal to: {a: docs, b: docs, c: docs}
var combined = [];
for (keys in results) {
combined = combined.concat(results[keys].splice(0,splice_length));
}
combined = dedup(combined); async.parallel(async_query, function(err, results) {
respond(combined); var splice_length = parseInt((SIZE / Object.keys(results).length), 10);
}); // results is equal to: {a: docs, b: docs, c: docs}
var combined = [];
for (keys in results) {
combined = combined.concat(results[keys].splice(0,splice_length));
}
combined = dedup(combined);
respond(combined);
});
} else {
query_backend(cmd, function(err, results) {
respond(results);
});
}
} }
return controller; return controller;

50
controller/suggest_admin.js

@ -1,50 +0,0 @@
/**
README: http://www.elasticsearch.org/guide/en/elasticsearch/client/javascript-api/current/api-reference.html#api-suggest
**/
var geojsonify = require('../helper/geojsonify').suggest;
function setup( backend, query ){
// allow overriding of dependencies
backend = backend || require('../src/backend');
query = query || require('../query/suggest_admin');
function controller( req, res, next ){
// backend command
var cmd = {
index: 'pelias',
body: query( req.clean )
};
// query backend
backend().client.suggest( cmd, function( err, data ){
var docs = [];
// handle backend errors
if( err ){ return next( err ); }
// map response to a valid FeatureCollection
if( data && Array.isArray( data.pelias ) && data.pelias.length ){
docs = data['pelias'][0].options || [];
}
// convert docs to geojson
var geojson = geojsonify( docs );
// response envelope
geojson.date = new Date().getTime();
// respond
return res.status(200).json( geojson );
});
}
return controller;
}
module.exports = setup;

46
controller/suggest_poi.js

@ -1,46 +0,0 @@
var geojsonify = require('../helper/geojsonify').suggest;
function setup( backend, query ){
// allow overriding of dependencies
backend = backend || require('../src/backend');
query = query || require('../query/suggest_poi');
function controller( req, res, next ){
// backend command
var cmd = {
index: 'pelias',
body: query( req.clean )
};
// query backend
backend().client.suggest( cmd, function( err, data ){
var docs = [];
// handle backend errors
if( err ){ return next( err ); }
// map response to a valid FeatureCollection
if( data && Array.isArray( data.pelias ) && data.pelias.length ){
docs = data['pelias'][0].options || [];
}
// convert docs to geojson
var geojson = geojsonify( docs );
// response envelope
geojson.date = new Date().getTime();
// respond
return res.status(200).json( geojson );
});
}
return controller;
}
module.exports = setup;

0
query/suggest_poi.js → query/suggest.js

29
query/suggest_admin.js

@ -1,29 +0,0 @@
var logger = require('../src/logger');
// Build pelias suggest query
function generate( params, precision ){
var cmd = {
'pelias' : {
'text' : params.input,
'completion' : {
'size' : params.size,
'field' : 'suggest',
'context': {
'dataset': ['admin0','admin1','admin2'],
'location': {
'value': [ params.lon, params.lat ],
'precision': precision || 1
}
}
}
}
};
// logger.log( 'cmd', JSON.stringify( cmd, null, 2 ) );
return cmd;
}
module.exports = generate;

15
test/unit/controller/suggest.js

@ -1,5 +1,5 @@
var setup = require('../../../controller/suggest_poi'), var setup = require('../../../controller/suggest'),
mockBackend = require('../mock/backend'), mockBackend = require('../mock/backend'),
mockQuery = require('../mock/query'); mockQuery = require('../mock/query');
@ -24,7 +24,7 @@ module.exports.tests.functional_success = function(test, common) {
coordinates: [ 101, -10.1 ] coordinates: [ 101, -10.1 ]
}, },
properties: { properties: {
id: 'mockid', id: 'mockid1',
type: 'mocktype', type: 'mocktype',
value: 1 value: 1
} }
@ -35,7 +35,7 @@ module.exports.tests.functional_success = function(test, common) {
coordinates: [ 101, -10.1 ] coordinates: [ 101, -10.1 ]
}, },
properties: { properties: {
id: 'mockid', id: 'mockid2',
type: 'mocktype', type: 'mocktype',
value: 2 value: 2
} }
@ -43,7 +43,12 @@ module.exports.tests.functional_success = function(test, common) {
test('functional success', function(t) { test('functional success', function(t) {
var backend = mockBackend( 'client/suggest/ok/1', function( cmd ){ var backend = mockBackend( 'client/suggest/ok/1', function( cmd ){
t.deepEqual(cmd, { body: { a: 'b' }, index: 'pelias' }, 'correct backend command'); if (cmd.body.layers) {
// layers are set exclusively for admin: test for admin-only layers
t.deepEqual(cmd, { body: { input: 'b', layers: [ 'admin0', 'admin1', 'admin2' ] }, index: 'pelias' }, 'correct backend command');
} else {
t.deepEqual(cmd, { body: { input: 'b' }, index: 'pelias' }, 'correct backend command');
}
}); });
var controller = setup( backend, mockQuery() ); var controller = setup( backend, mockQuery() );
var res = { var res = {
@ -60,7 +65,7 @@ module.exports.tests.functional_success = function(test, common) {
t.end(); t.end();
} }
}; };
controller( { clean: { a: 'b' } }, res ); controller( { clean: { input: 'b' } }, res );
}); });
}; };

10
test/unit/mock/backend.js

@ -1,12 +1,14 @@
var mockPayload = { var mockPayload = function(id){
id: 'mocktype/mockid', return {
geo: '101,-10.1' id: 'mocktype/mockid'+id,
geo: '101,-10.1'
}
}; };
var responses = {}; var responses = {};
responses['client/suggest/ok/1'] = function( cmd, cb ){ responses['client/suggest/ok/1'] = function( cmd, cb ){
return cb( undefined, suggestEnvelope([ { value: 1, payload: mockPayload }, { value: 2, payload: mockPayload } ]) ); return cb( undefined, suggestEnvelope([ { value: 1, payload: mockPayload(1) }, { value: 2, payload: mockPayload(2) } ]) );
}; };
responses['client/suggest/fail/1'] = function( cmd, cb ){ responses['client/suggest/fail/1'] = function( cmd, cb ){
return cb( 'a backend error occurred' ); return cb( 'a backend error occurred' );

2
test/unit/query/suggest.js

@ -1,5 +1,5 @@
var generate = require('../../../query/suggest_poi'); var generate = require('../../../query/suggest');
module.exports.tests = {}; module.exports.tests = {};

Loading…
Cancel
Save