mirror of https://github.com/pelias/api.git
Peter Johnson
8 years ago
committed by
missinglink
4 changed files with 198 additions and 0 deletions
@ -0,0 +1,136 @@ |
|||||||
|
|
||||||
|
var async = require('async'); |
||||||
|
var service = require('../service/interpolation')(); |
||||||
|
var logger = require( 'pelias-logger' ).get( 'api' ); |
||||||
|
|
||||||
|
/** |
||||||
|
example response from interpolation web service: |
||||||
|
{ |
||||||
|
type: 'Feature', |
||||||
|
properties: { |
||||||
|
type: 'interpolated', |
||||||
|
source: 'mixed', |
||||||
|
number: '17', |
||||||
|
lat: -41.2887032, |
||||||
|
lon: 174.767089 |
||||||
|
}, |
||||||
|
geometry: { |
||||||
|
type: 'Point', |
||||||
|
coordinates: [ 174.767089, -41.2887032 ] |
||||||
|
} |
||||||
|
} |
||||||
|
**/ |
||||||
|
|
||||||
|
function setup() { |
||||||
|
return function middleware(req, res, next) { |
||||||
|
|
||||||
|
// no-op, user did not request an address
|
||||||
|
if( !isAddressQuery( req ) ){ |
||||||
|
return next(); |
||||||
|
} |
||||||
|
|
||||||
|
// bind parsed_text variables to function call
|
||||||
|
var bound = interpolate.bind( null, req.clean.parsed_text ); |
||||||
|
|
||||||
|
// perform interpolations asynchronously for all relevant hits
|
||||||
|
var timer = (new Date()).getTime(); |
||||||
|
async.map( res.data, bound, function( err, results ){ |
||||||
|
|
||||||
|
// update res.data with the mapped values
|
||||||
|
if( !err ){ |
||||||
|
res.data = results; |
||||||
|
} |
||||||
|
|
||||||
|
// log the execution time, continue
|
||||||
|
logger.info( '[interpolation] [took]', (new Date()).getTime() - timer, 'ms' ); |
||||||
|
next(); |
||||||
|
}); |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
function interpolate( parsed_text, hit, cb ){ |
||||||
|
|
||||||
|
// no-op, this hit is not from the 'street' layer
|
||||||
|
// note: no network request is performed.
|
||||||
|
if( !hit || hit.layer !== 'street' ){ |
||||||
|
return cb( null, hit ); |
||||||
|
} |
||||||
|
|
||||||
|
// query variables
|
||||||
|
var coord = hit.center_point; |
||||||
|
var number = parsed_text.number; |
||||||
|
var street = hit.address_parts.street || parsed_text.street; |
||||||
|
|
||||||
|
// query interpolation service
|
||||||
|
service.query( coord, number, street, function( err, data ){ |
||||||
|
|
||||||
|
// an error occurred
|
||||||
|
// note: leave this hit unmodified
|
||||||
|
if( err ){ |
||||||
|
logger.error( '[interpolation] [error]', err ); |
||||||
|
return cb( null, hit ); |
||||||
|
} |
||||||
|
|
||||||
|
// invalid / not useful response
|
||||||
|
// note: leave this hit unmodified
|
||||||
|
if( !data || !data.hasOwnProperty('properties') ){ |
||||||
|
logger.info( '[interpolation] [miss]', parsed_text ); |
||||||
|
return cb( null, hit ); |
||||||
|
} |
||||||
|
|
||||||
|
// the interpolation service returned a valid result
|
||||||
|
// note: we now merge thos values with the existing 'street' record.
|
||||||
|
logger.info( '[interpolation] [hit]', parsed_text, data ); |
||||||
|
|
||||||
|
// safety first!
|
||||||
|
try { |
||||||
|
|
||||||
|
// -- metatdata --
|
||||||
|
hit.layer = 'address'; |
||||||
|
hit.match_type = 'interpolated'; |
||||||
|
|
||||||
|
// -- name --
|
||||||
|
hit.name.default = data.properties.number + ' ' + hit.name.default; |
||||||
|
|
||||||
|
// -- source --
|
||||||
|
var source = 'mixed'; |
||||||
|
if( data.properties.source === 'osm' ){ source = 'openstreetmap'; } |
||||||
|
else if( data.properties.source === 'oa' ){ source = 'openaddresses'; } |
||||||
|
hit.source = source; |
||||||
|
|
||||||
|
// -- source_id --
|
||||||
|
hit.source_id = 'derived:'+ hit.source_id; |
||||||
|
|
||||||
|
// -- address_parts --
|
||||||
|
hit.address_parts.number = data.properties.number; |
||||||
|
|
||||||
|
// -- geo --
|
||||||
|
hit.center_point = { |
||||||
|
lat: data.properties.lat, |
||||||
|
lon: data.properties.lon |
||||||
|
}; |
||||||
|
|
||||||
|
// -- bbox --
|
||||||
|
delete hit.bounding_box; |
||||||
|
|
||||||
|
// return the modified hit
|
||||||
|
return cb( null, hit ); |
||||||
|
|
||||||
|
// a syntax error occurred in the code above (this shouldn't happen!)
|
||||||
|
// note: the hit object may be partially modified, could possibly be invalid
|
||||||
|
} catch( e ){ |
||||||
|
logger.error( '[interpolation] [error]', e, e.stack ); |
||||||
|
return cb( null, hit ); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
// boolean function to check if an address was requested by the user
|
||||||
|
function isAddressQuery( req ){ |
||||||
|
return req && req.hasOwnProperty('clean') && |
||||||
|
req.clean.hasOwnProperty('parsed_text') && |
||||||
|
req.clean.parsed_text.hasOwnProperty('number') && |
||||||
|
req.clean.parsed_text.hasOwnProperty('street'); |
||||||
|
} |
||||||
|
|
||||||
|
module.exports = setup; |
@ -0,0 +1,58 @@ |
|||||||
|
|
||||||
|
var logger = require( 'pelias-logger' ).get( 'api' ); |
||||||
|
|
||||||
|
/** |
||||||
|
|
||||||
|
street address interpolation service |
||||||
|
|
||||||
|
see: https://github.com/pelias/interpolation
|
||||||
|
|
||||||
|
**/ |
||||||
|
|
||||||
|
/** |
||||||
|
RequireTransport |
||||||
|
|
||||||
|
allows the api to be used by simply requiring the module |
||||||
|
**/ |
||||||
|
function RequireTransport( addressDbPath, streetDbPath ){ |
||||||
|
try { |
||||||
|
var lib = require('pelias-interpolation'); |
||||||
|
this.query = lib.api.search( addressDbPath, streetDbPath ); |
||||||
|
} catch( e ){ |
||||||
|
logger.error( 'RequireTransport: failed to connect to interpolation service' ); |
||||||
|
} |
||||||
|
} |
||||||
|
RequireTransport.prototype.query = function( coord, number, street, cb ){ |
||||||
|
throw new Error( 'transport not connected' ); |
||||||
|
}; |
||||||
|
|
||||||
|
/** |
||||||
|
HttpTransport |
||||||
|
|
||||||
|
allows the api to be used via a remote web service |
||||||
|
**/ |
||||||
|
function HttpTransport( host ){ |
||||||
|
var request = require('superagent'); |
||||||
|
this.query = function( coord, number, street, cb ){ |
||||||
|
request |
||||||
|
.get( host + '/search/geojson' ) |
||||||
|
.set( 'Accept', 'application/json' ) |
||||||
|
.query({ lat: coord.lat, lon: coord.lon, number: number, street: street }) |
||||||
|
.end( function( err, res ){ |
||||||
|
if( err || !res ){ return cb( err ); } |
||||||
|
return cb( null, res.body ); |
||||||
|
}); |
||||||
|
}; |
||||||
|
} |
||||||
|
HttpTransport.prototype.query = function( coord, number, street, cb ){ |
||||||
|
throw new Error( 'transport not connected' ); |
||||||
|
}; |
||||||
|
|
||||||
|
/** |
||||||
|
Setup |
||||||
|
|
||||||
|
allows instantiation of transport depending on configuration and preference |
||||||
|
**/ |
||||||
|
module.exports = function setup(){ |
||||||
|
return new HttpTransport( 'http://interpolation.wiz.co.nz' ); |
||||||
|
}; |
Loading…
Reference in new issue