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.
130 lines
3.6 KiB
130 lines
3.6 KiB
8 years ago
|
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();
|
||
|
}
|
||
|
|
||
|
const centroid = {
|
||
|
lat: req.clean['point.lat'],
|
||
|
lon: req.clean['point.lon']
|
||
|
};
|
||
|
|
||
|
service(centroid, (err, results) => {
|
||
|
// if there's an error, log it and bail
|
||
|
if (err) {
|
||
|
logger.error(err);
|
||
|
return next();
|
||
|
}
|
||
|
|
||
|
// find the finest granularity requested
|
||
|
const finest_granularity_requested = granularities.findIndex((granularity) => {
|
||
|
return req.clean.layers.indexOf(granularity) !== -1;
|
||
|
});
|
||
|
|
||
|
// 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;
|