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
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 |
|
); |
|
}; |