Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add API filter targets to config #1131

Merged
merged 8 commits into from
May 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ The API recognizes the following properties under the top-level `api` key in you
|`accessLog`|*no*||name of the format to use for access logs; may be any one of the [predefined values](https://github.com/expressjs/morgan#predefined-formats) in the `morgan` package. Defaults to `"common"`; if set to `false`, or an otherwise falsy value, disables access-logging entirely.|
|`services`|*no*||service definitions for [point-in-polygon](https://github.com/pelias/pip-service), [libpostal](https://github.com/whosonfirst/go-whosonfirst-libpostal), [placeholder](https://github.com/pelias/placeholder), and [interpolation](https://github.com/pelias/interpolation) services. If missing (which is not recommended), the services will not be called.|
|`defaultParameters.focus.point.lon` <br> `defaultParameters.focus.point.lat`|no | |default coordinates for focus point
|`targets.layers_by_source` <br> `targets.source_aliases` <br> `targets.layer_aliases`|no | |custom values for which `sources` and `layers` the API accepts ([more info](https://github.com/pelias/api/pull/1131)).

A good starting configuration file includes this section (fill in the service and Elasticsearch hosts as needed):

Expand Down
146 changes: 146 additions & 0 deletions helper/TypeMapping.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
const _ = require('lodash');
const elasticsearch = require('elasticsearch');

var TypeMapping = function(){

// A list of all sources
this.sources = [];

// A list of alternate names for sources, mostly used to save typing
this.source_aliases = {};

// A list of all layers
this.layers = [];

/*
* A list of all layers in each source. This is used for convenience elswhere
* and to determine when a combination of source and layer parameters is
* not going to match any records and will return no results.
*/
this.layers_by_source = {};

/*
* A list of layer aliases that can be used to support specific use cases
* (like coarse geocoding) * or work around the fact that different sources
* may have layers that mean the same thing but have a different name
*/
this.layer_aliases = {};

/*
* An object that contains all sources or aliases. The key is the source or alias,
* the value is either that source, or the canonical name for that alias if it's an alias.
*/
this.source_mapping = {};

/*
* An object that has a key for each possible layer or alias,
* and returns either that layer, or gall the layers in the alias
*/
this.layer_mapping = {};
};

TypeMapping.addStandardTargetsToAliases = function(standard, aliases) {
var combined = _.extend({}, aliases);
standard.forEach(function(target) {
if (combined[target] === undefined) {
combined[target] = [target];
}
});

return combined;
};

// source alias setter
TypeMapping.prototype.setSourceAliases = function( aliases ){
this.source_aliases = aliases;
};

// layers-by-source alias setter
TypeMapping.prototype.setLayersBySource = function( lbs ){
this.layers_by_source = lbs;
};

// layer alias setter
TypeMapping.prototype.setLayerAliases = function( aliases ){
this.layer_aliases = aliases;
};

// generate mappings after setters have been run
TypeMapping.prototype.generateMappings = function(){
this.sources = Object.keys( this.layers_by_source );
this.source_mapping = TypeMapping.addStandardTargetsToAliases(this.sources, this.source_aliases);
this.layers = _.uniq(Object.keys(this.layers_by_source).reduce(function(acc, key) {
return acc.concat(this.layers_by_source[key]);
}.bind(this), []));
this.layer_mapping = TypeMapping.addStandardTargetsToAliases(this.layers, this.layer_aliases);
};

// load values from targets block
TypeMapping.prototype.loadTargets = function( targetsBlock ){

if( !_.isObject(targetsBlock) ){ return; }

// set values from targets block
this.setSourceAliases( targetsBlock.source_aliases || {} );
this.setLayersBySource( targetsBlock.layers_by_source || {} );
this.setLayerAliases( targetsBlock.layer_aliases || {} );

// generate the mappings
this.generateMappings();
};

// load values from either pelias config file or from elasticsearch
TypeMapping.prototype.load = function( done ){

// load pelias config
const peliasConfigTargets = _.get(
require('pelias-config').generate(require('../schema')),
'api.targets', {}
);

// load targets from config file
this.loadTargets( peliasConfigTargets );

// do not load values from elasticsearch
if( true !== peliasConfigTargets.auto_discover ){
if( 'function' === typeof done ){ done(); }
return;
}

if( 'function' === typeof done ){ done(); }
return;

// load values from elasticsearch

// create connection to elasticsearch
// const esclient = elasticsearch.Client(peliasConfig.esclient);

// const query = {
// requestCache: true,
// preference: '_replica_first',
// timeout: '10s',
// body: {
// aggs: {
// sources: {
// terms: {
// field: 'source',
// size: 100
// }
// },
// layers: {
// terms: {
// field: 'layer',
// size: 100
// }
// }
// },
// size: 0
// }
// };

// esclient.search( query, ( err, res ) => {
// console.error( err, res );
// });
};

module.exports = TypeMapping;
90 changes: 6 additions & 84 deletions helper/type_mapping.js
Original file line number Diff line number Diff line change
@@ -1,86 +1,8 @@
const _ = require('lodash');
const TypeMapping = require('./TypeMapping');

function addStandardTargetsToAliases(standard, aliases) {
var combined = _.extend({}, aliases);
standard.forEach(function(target) {
if (combined[target] === undefined) {
combined[target] = [target];
}
});
// instantiate a new type mapping
var tm = new TypeMapping();
tm.load();

return combined;
}

/*
* Sources
*/

// a list of all sources
var SOURCES = ['openstreetmap', 'openaddresses', 'geonames', 'whosonfirst'];

/*
* A list of alternate names for sources, mostly used to save typing
*/
var SOURCE_ALIASES = {
'osm': ['openstreetmap'],
'oa': ['openaddresses'],
'gn': ['geonames'],
'wof': ['whosonfirst']
};

/*
* Create an object that contains all sources or aliases. The key is the source or alias,
* the value is either that source, or the canonical name for that alias if it's an alias.
*/
var SOURCE_MAPPING = addStandardTargetsToAliases(SOURCES, SOURCE_ALIASES);

/*
* Layers
*/

/*
* A list of all layers in each source. This is used for convenience elswhere
* and to determine when a combination of source and layer parameters is
* not going to match any records and will return no results.
*/
var LAYERS_BY_SOURCE = {
openstreetmap: [ 'address', 'venue', 'street' ],
openaddresses: [ 'address' ],
geonames: [ 'country','macroregion', 'region', 'county','localadmin',
'locality','borough', 'neighbourhood', 'venue' ],
whosonfirst: [ 'continent', 'empire', 'country', 'dependency', 'macroregion', 'region',
'locality', 'localadmin', 'macrocounty', 'county', 'macrohood', 'borough',
'neighbourhood', 'microhood', 'disputed', 'venue', 'postalcode',
'continent', 'ocean', 'marinearea']
};

/*
* A list of layer aliases that can be used to support specific use cases
* (like coarse geocoding) * or work around the fact that different sources
* may have layers that mean the same thing but have a different name
*/
var LAYER_ALIASES = {
'coarse': [ 'continent', 'empire', 'country', 'dependency', 'macroregion',
'region', 'locality', 'localadmin', 'macrocounty', 'county', 'macrohood',
'borough', 'neighbourhood', 'microhood', 'disputed', 'postalcode',
'continent', 'ocean', 'marinearea']
};

// create a list of all layers by combining each entry from LAYERS_BY_SOURCE
var LAYERS = _.uniq(Object.keys(LAYERS_BY_SOURCE).reduce(function(acc, key) {
return acc.concat(LAYERS_BY_SOURCE[key]);
}, []));

/*
* Create the an object that has a key for each possible layer or alias,
* and returns either that layer, or all the layers in the alias
*/
var LAYER_MAPPING = addStandardTargetsToAliases(LAYERS, LAYER_ALIASES);

module.exports = {
sources: SOURCES,
layers: LAYERS,
source_mapping: SOURCE_MAPPING,
layer_mapping: LAYER_MAPPING,
layers_by_source: LAYERS_BY_SOURCE
};
// export singleton
module.exports = tm;
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@
"node": ">=6.0.0"
},
"dependencies": {
"@mapbox/geojson-extent": "^0.3.1",
"addressit": "1.5.0",
"async": "^2.0.0",
"check-types": "^7.0.0",
"elasticsearch": "^14.2.1",
"elasticsearch-exceptions": "0.0.4",
"express": "^4.8.8",
"geojson": "^0.5.0",
"@mapbox/geojson-extent": "^0.3.1",
"geolib": "^2.0.18",
"iso-639-3": "^1.0.0",
"iso3166-1": "^0.3.0",
Expand All @@ -53,7 +53,7 @@
"markdown": "0.5.0",
"morgan": "^1.8.2",
"pelias-categories": "1.2.0",
"pelias-config": "2.14.0",
"pelias-config": "2.15.0",
"pelias-labels": "1.8.0",
"pelias-logger": "0.3.1",
"pelias-microservice-wrapper": "1.3.0",
Expand Down
Loading