mirror of https://github.com/pelias/api.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
127 lines
3.7 KiB
127 lines
3.7 KiB
const logger = require('pelias-logger').get('coarse_reverse'); |
|
const _ = require('lodash'); |
|
const Document = require('pelias-model').Document; |
|
|
|
const granularities = [ |
|
'neighbourhood', |
|
'borough', |
|
'locality', |
|
'localadmin', |
|
'county', |
|
'macrocounty', |
|
'region', |
|
'macroregion', |
|
'dependency', |
|
'country' |
|
]; |
|
|
|
function getMostGranularLayer(results) { |
|
return granularities.find((granularity) => { |
|
return results.hasOwnProperty(granularity); |
|
}); |
|
} |
|
|
|
function hasResultsAtRequestedLayers(results, layers) { |
|
return _.intersection(layers, Object.keys(results)).length > 0; |
|
} |
|
|
|
function synthesizeDoc(results) { |
|
// now create a model.Document from what's level, using the most granular |
|
// result available as the starting point |
|
// the immediately above cannot be re-used since county may be the most |
|
// granular layer requested but the results may start at region (no county found) |
|
const most_granular_layer = getMostGranularLayer(results); |
|
const id = results[most_granular_layer][0].id; |
|
|
|
const doc = new Document('whosonfirst', most_granular_layer, id.toString()); |
|
doc.setName('default', results[most_granular_layer][0].name); |
|
|
|
if (results[most_granular_layer][0].hasOwnProperty('centroid')) { |
|
doc.setCentroid( results[most_granular_layer][0].centroid ); |
|
} |
|
|
|
if (results[most_granular_layer][0].hasOwnProperty('bounding_box')) { |
|
const parsedBoundingBox = results[most_granular_layer][0].bounding_box.split(',').map(parseFloat); |
|
doc.setBoundingBox({ |
|
upperLeft: { |
|
lat: parsedBoundingBox[3], |
|
lon: parsedBoundingBox[0] |
|
}, |
|
lowerRight: { |
|
lat: parsedBoundingBox[1], |
|
lon: parsedBoundingBox[2] |
|
} |
|
}); |
|
|
|
} |
|
|
|
if (_.has(results, 'country[0].abbr')) { |
|
doc.setAlpha3(results.country[0].abbr); |
|
} |
|
|
|
// assign the administrative hierarchy |
|
Object.keys(results).forEach((layer) => { |
|
if (results[layer][0].hasOwnProperty('abbr')) { |
|
doc.addParent(layer, results[layer][0].name, results[layer][0].id.toString(), results[layer][0].abbr); |
|
} else { |
|
doc.addParent(layer, results[layer][0].name, results[layer][0].id.toString()); |
|
} |
|
|
|
}); |
|
|
|
const esDoc = doc.toESDocument(); |
|
esDoc.data._id = esDoc._id; |
|
esDoc.data._type = esDoc._type; |
|
return esDoc.data; |
|
|
|
} |
|
|
|
function setup(service, should_execute) { |
|
function controller(req, res, next) { |
|
// do not run controller when a request validation error has occurred |
|
if (!should_execute(req, res)) { |
|
return next(); |
|
} |
|
|
|
service(req, (err, results) => { |
|
// if there's an error, log it and bail |
|
if (err) { |
|
logger.info(`[controller:coarse_reverse][error]`); |
|
logger.error(err); |
|
return next(); |
|
} |
|
|
|
// find the finest granularity requested |
|
const finest_granularity_requested = granularities.findIndex((granularity) => { |
|
return req.clean.layers.indexOf(granularity) !== -1; |
|
}); |
|
|
|
logger.info(`[controller:coarse_reverse][queryType:pip][result_count:${Object.keys(results).length}]`); |
|
|
|
// now remove everything from the response that is more granular than the |
|
// most granular layer requested. that is, if req.clean.layers=['county'], |
|
// remove neighbourhoods, localities, and localadmins |
|
Object.keys(results).forEach((layer) => { |
|
if (granularities.indexOf(layer) < finest_granularity_requested) { |
|
delete results[layer]; |
|
} |
|
}); |
|
|
|
res.meta = {}; |
|
res.data = []; |
|
// synthesize a doc from results if there's a result at the request layer(s) |
|
if (hasResultsAtRequestedLayers(results, req.clean.layers)) { |
|
res.data.push(synthesizeDoc(results)); |
|
} |
|
|
|
return next(); |
|
|
|
}); |
|
|
|
} |
|
|
|
return controller; |
|
|
|
} |
|
|
|
module.exports = setup;
|
|
|