diff --git a/controller/suggest.js b/controller/suggest.js index 425b7415..12269fef 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 ){ @@ -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); + 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,6 +55,35 @@ 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[1] + }; + }); + + 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; diff --git a/controller/suggest_nearby.js b/controller/suggest_nearby.js index 956363b8..b0a30f70 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[1] + }; + }); + + 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