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.3 KiB

var queries = require('geopipes-elasticsearch-backend').queries,
sort = require('../query/sort'),
adminFields = require('../helper/adminFields').availableFields,
addressWeights = require('../helper/address_weights');
function generate( params ){
var centroid = null;
if ( params.lat && params.lon ){
centroid = {
lat: params.lat,
lon: params.lon
};
}
var query = queries.distance( centroid, { size: params.size } );
var input = params.input;
if (params.bbox) {
query = queries.bbox ( centroid, { size: params.size, bbox: params.bbox } );
}
query.query.filtered.query = {
'bool': {
'must': [],
'should': []
}
};
if (params.parsed_input) {
addParsedMatch(query, input, params.parsed_input);
// update input
if (params.parsed_input.number && params.parsed_input.street) {
input = params.parsed_input.number + ' ' + params.parsed_input.street;
} else if (params.parsed_input.admin_parts) {
input = params.parsed_input.name;
}
}
// add search condition to distance query
query.query.filtered.query.bool.must.push({
'match': {
'name.default': input
}
});
// add phrase matching query
// note: this is required for shingle/phrase matching
query.query.filtered.query.bool.should.push({
'match': {
'phrase.default': input
}
});
query.sort = query.sort.concat( sort( params ) );
return query;
}
function addParsedMatch(query, defaultInput, parsedInput) {
query.query.filtered.query.bool.should = [];
// copy expected admin fields so we can remove them as we parse the address
var unmatchedAdminFields = adminFields.slice();
// address
// number, street, postalcode
addMatch(query, unmatchedAdminFields, 'address.number', parsedInput.number, addressWeights.number);
addMatch(query, unmatchedAdminFields, 'address.street', parsedInput.street, addressWeights.street);
addMatch(query, unmatchedAdminFields, 'address.zip', parsedInput.postalcode, addressWeights.zip);
// city
// admin2, locality, local_admin, neighborhood
addMatch(query, unmatchedAdminFields, 'admin2', parsedInput.admin2, addressWeights.admin2);
// state
// admin1, admin1_abbr
addMatch(query, unmatchedAdminFields, 'admin1_abbr', parsedInput.state, addressWeights.admin1_abbr);
// country
// admin0, alpha3
addMatch(query, unmatchedAdminFields, 'alpha3', parsedInput.country, addressWeights.alpha3);
var inputRegions = parsedInput.regions ? parsedInput.regions.join(' ') : undefined;
// if no address was identified and input suggests some admin info in it
if (unmatchedAdminFields.length > 0 && inputRegions !== defaultInput) {
unmatchedAdminFields.forEach(function (key) {
if (parsedInput.admin_parts) {
addMatch(query, [], key, parsedInput.admin_parts);
}
else {
addMatch(query, [], key, inputRegions);
}
});
}
}
function addMatch(query, unmatched, key, value, boost) { // jshint ignore:line
if (typeof value === 'undefined') {
return;
}
var match = {};
if (boost) {
match[key] = {
query: value,
boost: boost
};
}
else {
match[key] = value;
}
query.query.filtered.query.bool.should.push({ 'match': match });
var index = unmatched.indexOf(key);
if (index !== -1) {
unmatched.splice(index, 1);
}
}
module.exports = generate;