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.
163 lines
6.2 KiB
163 lines
6.2 KiB
7 years ago
|
const all = require('predicates').all;
|
||
|
const any = require('predicates').any;
|
||
|
const not = require('predicates').not;
|
||
|
|
||
|
const sanitizers = require('../../sanitizer');
|
||
|
const predicates = require('../../controller/predicates');
|
||
|
const controllers = require('../../controller');
|
||
|
const queries = require('../../query');
|
||
|
const postProc = require('../../middleware');
|
||
|
|
||
|
const utils = require('./utils');
|
||
|
|
||
|
module.exports.create = (peliasConfig, esclient, services) => {
|
||
|
|
||
|
// helpers to replace vague booleans
|
||
|
const geometricFiltersApply = true;
|
||
|
const geometricFiltersDontApply = false;
|
||
|
|
||
|
return utils.createRouter([
|
||
|
sanitizers.search.middleware(peliasConfig.api),
|
||
|
postProc.requestLanguage,
|
||
|
postProc.calcSize(),
|
||
|
controllers.libpostal(libpostalShouldExecute()),
|
||
|
controllers.placeholder(services.placeholder.service, geometricFiltersApply, placeholderGeodisambiguationShouldExecute(services)),
|
||
|
controllers.placeholder(services.placeholder.service, geometricFiltersDontApply, placeholderIdsLookupShouldExecute(services)),
|
||
|
controllers.search_with_ids(peliasConfig.api, esclient, queries.address_using_ids, searchWithIdsShouldExecute()),
|
||
|
controllers.search_with_appending_results(peliasConfig.api, esclient, queries.venues, venuesSearchShouldExecute()),
|
||
|
// 3rd parameter is which query module to use, use fallback first, then
|
||
|
// use original search strategy if first query didn't return anything
|
||
|
controllers.search(peliasConfig.api, esclient, queries.cascading_fallback, fallbackQueryShouldExecute(services)),
|
||
|
sanitizers.defer_to_addressit(shouldDeferToAddressIt(services)),
|
||
|
controllers.search(peliasConfig.api, esclient, queries.very_old_prod, oldProdQueryShouldExecute()),
|
||
|
postProc.trimByGranularity(),
|
||
|
postProc.distances('focus.point.'),
|
||
|
postProc.confidenceScores(peliasConfig.api),
|
||
|
postProc.confidenceScoresFallback(),
|
||
|
postProc.interpolate(services.interpolation.service, utils.interpolationShouldExecute(services)),
|
||
|
postProc.sortResponseData(require('pelias-sorting'), predicates.hasAdminOnlyResults),
|
||
|
postProc.dedupe(),
|
||
|
postProc.accuracy(),
|
||
|
postProc.localNamingConventions(),
|
||
|
postProc.renamePlacenames(),
|
||
|
postProc.parseBoundingBox(),
|
||
|
postProc.normalizeParentIds(),
|
||
|
postProc.changeLanguage(services.language.service, utils.changeLanguageShouldExecute(services)),
|
||
|
postProc.assignLabels(),
|
||
|
postProc.geocodeJSON(peliasConfig.api, utils.base),
|
||
|
postProc.sendJSON
|
||
|
]);
|
||
|
};
|
||
|
|
||
|
// search for venues under the following conditions:
|
||
|
// - there are no request errors
|
||
|
// - analysis is only admin (no address, query, or street)
|
||
|
// - there's a single field in analysis
|
||
|
// - request has a focus.point available
|
||
|
// - TODO: needs check for venues is in layers
|
||
|
// https://github.com/pelias/pelias/issues/564
|
||
|
const venuesSearchShouldExecute = () => {
|
||
|
return all(
|
||
|
not(predicates.hasRequestErrors),
|
||
|
predicates.isVenueLayerRequested,
|
||
|
predicates.isAdminOnlyAnalysis,
|
||
|
predicates.isSingleFieldAnalysis,
|
||
|
predicates.hasRequestFocusPoint
|
||
|
);
|
||
|
};
|
||
|
|
||
|
const libpostalShouldExecute = () => {
|
||
|
return all(
|
||
|
not(predicates.hasRequestErrors),
|
||
|
not(predicates.isRequestSourcesOnlyWhosOnFirst)
|
||
|
);
|
||
|
};
|
||
|
|
||
|
const searchWithIdsShouldExecute = () => {
|
||
|
return all(
|
||
|
not(predicates.hasRequestErrors),
|
||
|
// don't search-with-ids if there's a query or category
|
||
|
not(predicates.hasParsedTextProperties.any('query', 'category')),
|
||
|
// there must be a street
|
||
|
predicates.hasParsedTextProperties.any('street')
|
||
|
);
|
||
|
};
|
||
|
|
||
|
|
||
|
// execute placeholder if libpostal only parsed as admin-only and needs to
|
||
|
// be geodisambiguated
|
||
|
const placeholderGeodisambiguationShouldExecute = (services) => {
|
||
|
return all(
|
||
|
not(predicates.hasResponseDataOrRequestErrors),
|
||
|
services.placeholder.isEnabled,
|
||
|
// check request.clean for several conditions first
|
||
|
not(
|
||
|
any(
|
||
|
// layers only contains venue, address, or street
|
||
|
predicates.isOnlyNonAdminLayers,
|
||
|
// don't geodisambiguate if categories were requested
|
||
|
predicates.hasRequestCategories
|
||
|
)
|
||
|
),
|
||
|
any(
|
||
|
// only geodisambiguate if libpostal returned only admin areas or libpostal was skipped
|
||
|
predicates.isAdminOnlyAnalysis,
|
||
|
predicates.isRequestSourcesOnlyWhosOnFirst
|
||
|
)
|
||
|
);
|
||
|
};
|
||
|
|
||
|
// execute placeholder if libpostal identified address parts but ids need to
|
||
|
// be looked up for admin parts
|
||
|
const placeholderIdsLookupShouldExecute = (services) => {
|
||
|
return all(
|
||
|
not(predicates.hasResponseDataOrRequestErrors),
|
||
|
services.placeholder.isEnabled,
|
||
|
// check clean.parsed_text for several conditions that must all be true
|
||
|
all(
|
||
|
// run placeholder if clean.parsed_text has 'street'
|
||
|
predicates.hasParsedTextProperties.any('street'),
|
||
|
// don't run placeholder if there's a query or category
|
||
|
not(predicates.hasParsedTextProperties.any('query', 'category')),
|
||
|
// run placeholder if there are any admin areas identified
|
||
|
predicates.hasParsedTextProperties.any('neighbourhood', 'borough', 'city', 'county', 'state', 'country')
|
||
|
)
|
||
|
);
|
||
|
};
|
||
|
|
||
|
// placeholder should have executed, useful for determining whether to actually
|
||
|
// fallback or not (don't fallback to old search if the placeholder response
|
||
|
// should be honored as is)
|
||
|
const placeholderShouldHaveExecuted = (services) => {
|
||
|
return any(
|
||
|
placeholderGeodisambiguationShouldExecute(services),
|
||
|
placeholderIdsLookupShouldExecute(services)
|
||
|
);
|
||
|
};
|
||
|
|
||
|
// don't execute the cascading fallback query IF placeholder should have executed
|
||
|
// that way, if placeholder didn't return anything, don't try to find more things the old way
|
||
|
const fallbackQueryShouldExecute = (services) => {
|
||
|
return all(
|
||
|
not(predicates.hasRequestErrors),
|
||
|
not(predicates.hasResponseData),
|
||
|
not(placeholderShouldHaveExecuted(services))
|
||
|
);
|
||
|
};
|
||
|
|
||
|
// defer to addressit for analysis IF there's no response AND placeholder should not have executed
|
||
|
const shouldDeferToAddressIt = (services) => {
|
||
|
return all(
|
||
|
not(predicates.hasRequestErrors),
|
||
|
not(predicates.hasResponseData),
|
||
|
not(placeholderShouldHaveExecuted(services))
|
||
|
);
|
||
|
};
|
||
|
|
||
|
// call very old prod query if addressit was the parser
|
||
|
const oldProdQueryShouldExecute = () => {
|
||
|
return all(
|
||
|
not(predicates.hasRequestErrors),
|
||
|
predicates.isAddressItParse
|
||
|
);
|
||
|
};
|