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