diff --git a/controller/suggest.js b/controller/suggest.js index 425b7415..f39f89d7 100644 --- a/controller/suggest.js +++ b/controller/suggest.js @@ -1,6 +1,9 @@ -var service = { suggest: require('../service/suggest') }; -var geojsonify = require('../helper/geojsonify').suggest; +var service = { + suggest: require('../service/suggest'), + mget: require('../service/mget') +}; +var geojsonify = require('../helper/geojsonify').search; var async = require('async'); function setup( backend, query ){ @@ -21,7 +24,7 @@ function setup( backend, query ){ var query_backend = function(cmd, callback) { // query backend service.suggest( backend, cmd, function( err, docs ){ - + // error handler if( err ){ return next( err ); } @@ -32,18 +35,18 @@ function setup( backend, query ){ var dedup = function(combined) { var unique_ids = []; return combined.filter(function(item, pos) { - if (unique_ids.indexOf(item.payload.id) == -1) { - unique_ids.push(item.payload.id); - return true; + if (unique_ids.indexOf(item.text) == -1) { + unique_ids.push(item.text); + return true; } return false; }); }; - var respond = function(data) { - + var reply = function(docs) { + // convert docs to geojson - var geojson = geojsonify( data ); + var geojson = geojsonify( docs ); // response envelope geojson.date = new Date().getTime(); @@ -52,12 +55,41 @@ function setup( backend, query ){ return res.status(200).json( geojson ); }; + var respond = function(data) { + + // no documents suggested, return empty array to avoid ActionRequestValidationException + if( !Array.isArray( data ) || !data.length ){ + return reply([]); + } + + // map suggester output to mget query + var query = data.map( function( doc ) { + var idParts = doc.text.split(':'); + return { + _index: 'pelias', + _type: idParts[0], + _id: idParts.slice(1).join(':') + }; + }); + + service.mget( backend, query, function( err, docs ){ + + // error handler + if( err ){ return next( err ); } + + // reply + return reply( docs ); + + }); + + }; + if (req.clean.input) { var async_query; // admin only req.admin = {}; - for (k in req.clean) { req.admin[k] = req.clean[k] } + for (var k in req.clean) { req.admin[k] = req.clean[k]; } req.admin.layers = ['admin0','admin1','admin2']; if (req.clean.input.length < 4 && isNaN(parseInt(req.clean.input, 10))) { @@ -74,7 +106,7 @@ function setup( backend, query ){ cmd.body = query( req.clean, 3 ); query_backend(cmd, callback); } - } + }; } else { async_query = { all_5p: function(callback){ @@ -93,7 +125,7 @@ function setup( backend, query ){ cmd.body = query( req.admin ); query_backend(cmd, callback); } - } + }; } async.parallel(async_query, function(err, results) { @@ -101,7 +133,7 @@ function setup( backend, query ){ var splice_length = parseInt((SIZE / Object.keys(results).length), 10); var results_keys = Object.keys(async_query); - var combined = []; + var combined = []; results_keys.forEach(function(key){ combined = combined.concat(results[key].splice(0,splice_length)); }); diff --git a/controller/suggest_nearby.js b/controller/suggest_nearby.js index 956363b8..6016cb7f 100644 --- a/controller/suggest_nearby.js +++ b/controller/suggest_nearby.js @@ -1,6 +1,9 @@ -var service = { suggest: require('../service/suggest') }; -var geojsonify = require('../helper/geojsonify').suggest; +var service = { + suggest: require('../service/suggest'), + mget: require('../service/mget') +}; +var geojsonify = require('../helper/geojsonify').search; function setup( backend, query ){ @@ -16,12 +19,9 @@ function setup( backend, query ){ body: query( req.clean ) }; - // query backend - service.suggest( backend, cmd, function( err, docs ){ - - // error handler - if( err ){ return next( err ); } - + // responder + function reply( docs ){ + // convert docs to geojson var geojson = geojsonify( docs ); @@ -30,6 +30,38 @@ function setup( backend, query ){ // respond return res.status(200).json( geojson ); + } + + // query backend + service.suggest( backend, cmd, function( err, suggested ){ + + // error handler + if( err ){ return next( err ); } + + // no documents suggested, return empty array to avoid ActionRequestValidationException + if( !Array.isArray( suggested ) || !suggested.length ){ + return reply([]); + } + + // map suggester output to mget query + var query = suggested.map( function( doc ) { + var idParts = doc.text.split(':'); + return { + _index: 'pelias', + _type: idParts[0], + _id: idParts.slice(1).join(':') + }; + }); + + service.mget( backend, query, function( err, docs ){ + + // error handler + if( err ){ return next( err ); } + + // reply + return reply( docs ); + + }); }); } diff --git a/helper/geojsonify.js b/helper/geojsonify.js index d4263900..630f12be 100644 --- a/helper/geojsonify.js +++ b/helper/geojsonify.js @@ -1,7 +1,8 @@ -var GeoJSON = require('geojson'); +var GeoJSON = require('geojson'), + outputGenerator = require('./outputGenerator'); -function suggest( docs ){ +function search( docs ){ // emit a warning if the doc format is invalid // @note: if you see this error, fix it ASAP! @@ -14,50 +15,14 @@ function suggest( docs ){ var geodata = docs.map( function( doc ){ // something went very wrong - if( !doc || !doc.payload ) return warning(); - - // split payload id string in to geojson properties - if( 'string' !== typeof doc.payload.id ) return warning(); - var idParts = doc.payload.id.split('/'); - doc.type = idParts[0]; - doc.id = idParts[1]; - - // split payload geo string in to geojson properties - if( 'string' !== typeof doc.payload.geo ) return warning(); - var geoParts = doc.payload.geo.split(','); - doc.lat = parseFloat( geoParts[1] ); - doc.lng = parseFloat( geoParts[0] ); - - // remove payload from doc - delete doc.payload; - return doc; - - // filter-out invalid entries - }).filter( function( doc ){ - return doc; - }); - - // convert to geojson - return GeoJSON.parse( geodata, { Point: ['lat', 'lng'] } ); - -} - -function search( docs ){ - - // emit a warning if the doc format is invalid - // @note: if you see this error, fix it ASAP! - function warning(){ - console.error( 'error: invalid doc', __filename ); - return false; // remove offending doc from results - } - - // flatten & expand data for geojson conversion - var geodata = docs.map( function( doc ){ + if( !doc ) return warning(); var output = {}; - // something went very wrong - if( !doc ) return warning(); + // provide metadata to consumer + output.id = doc._id; + output.type = doc._type; + output.layer = doc._type; // map center_point if( !doc.center_point ) return warning(); @@ -78,10 +43,8 @@ function search( docs ){ if( doc.locality ){ output.locality = doc.locality; } if( doc.neighborhood ){ output.neighborhood = doc.neighborhood; } - // map suggest output - if( doc.suggest && doc.suggest.output ){ - output.text = doc.suggest.output; - } + // generate region-specific text string + output.text = outputGenerator( doc ); return output; @@ -95,5 +58,4 @@ function search( docs ){ } -module.exports.suggest = suggest; module.exports.search = search; \ No newline at end of file diff --git a/helper/outputGenerator.js b/helper/outputGenerator.js new file mode 100644 index 00000000..42fa1279 --- /dev/null +++ b/helper/outputGenerator.js @@ -0,0 +1,37 @@ + +var schemas = require('./outputSchema.json'); + +module.exports = function( record ){ + + var adminParts = []; + + var schema = schemas.default; + + if (record.alpha3 && record.alpha3.length && schemas[record.alpha3]) { + schema = schemas[record.alpha3]; + } + + var buildOutput = function(parts, schemaArr, record) { + for (var i=0; i