Browse Source

WIP: Configurable boosts for sources and layers

This is a work in progress to enable customizing boosts for sources and
layers.

For now, the config must be hardcoded in query/autocomplete.js, but it
will eventually be driven by `pelias.json` and take effect on all
endpoints.
cb_sorting
Julian Simioni 6 years ago
parent
commit
faac4da4aa
No known key found for this signature in database
GPG Key ID: B9EEB0C6EE0910A1
  1. 13
      query/autocomplete.js
  2. 48
      query/view/boost_sources_and_layers.js
  3. 98
      test/unit/query/view/boost_sources_and_layers.js
  4. 5
      test/unit/run.js

13
query/autocomplete.js

@ -45,6 +45,19 @@ query.score( peliasQuery.view.focus( views.ngrams_strict ) );
query.score( peliasQuery.view.popularity( views.pop_subquery ) ); query.score( peliasQuery.view.popularity( views.pop_subquery ) );
query.score( peliasQuery.view.population( views.pop_subquery ) ); query.score( peliasQuery.view.population( views.pop_subquery ) );
const boostView = require( './view/boost_sources_and_layers' );
const boostConfig = {}; //TODO: empty config to make functional tests pass for now
// example useful config:
//const boostConfig = {
//layer: {
//stops: 5,
//fare: 5,
//station: 1
//},
//};
query.score( boostView(boostConfig) );
// non-scoring hard filters // non-scoring hard filters
query.filter( peliasQuery.view.sources ); query.filter( peliasQuery.view.sources );
query.filter( peliasQuery.view.layers ); query.filter( peliasQuery.view.layers );

48
query/view/boost_sources_and_layers.js

@ -0,0 +1,48 @@
//example input
//{
// "source": {
// "openstreetmap": 5
// },
// "layer": {
// "street": 3,
// "country": 5
// }
//}
function generateTermQuery(field, value, boost) {
return {
constant_score: {
boost: boost,
query: {
term: {
[field]: value,
}
}
}
};
}
module.exports = function( configuration ) {
return function( ) {
const filters = [];
['source', 'layer'].forEach(function(target) {
if (configuration[target]) {
Object.keys(configuration[target]).forEach(function(item) {
filters.push(generateTermQuery(target, item, configuration[target][item]));
});
}
});
if (filters.length === 0) {
return null;
} else if (filters.length === 1) {
return filters[0];
} else {
return {
bool: {
should: filters
}
};
}
};
};

98
test/unit/query/view/boost_sources_and_layers.js

@ -0,0 +1,98 @@
const boost_sources_and_layers = require('../../../../query/view/boost_sources_and_layers');
module.exports.tests = {};
module.exports.tests.empty_config = function(test, common) {
test('empty configuration returns empty query', function(t) {
const view_instance = boost_sources_and_layers({});
const query = view_instance();
t.equal(query, null, 'query is empty');
t.end();
});
};
module.exports.tests.single_item_config = function(test, common) {
test('config with single layer entry returns single term query with boost', function(t) {
const config = {
layer: {
locality: 5
}
};
const expected_query = {
constant_score: {
boost: 5,
query: {
term: {
layer: 'locality'
}
}
}
};
const view_instance = boost_sources_and_layers(config);
t.deepEquals(view_instance(), expected_query, 'query is a single term query');
t.end();
});
};
module.exports.tests.mulitple_item_config = function(test, common) {
test('config with multiple items returns bool query with multiple should conditions', function(t) {
const config = {
source: {
whosonfirst: 6
},
layer: {
country: 2,
borough: 0.5
},
};
const expected_query = {
bool: {
should: [{
constant_score: {
boost: 6,
query: {
term: {
source: 'whosonfirst',
}
}
}
}, {
constant_score: {
boost: 2,
query: {
term: {
layer: 'country'
}
}
}
},{
constant_score: {
boost: 0.5,
query: {
term: {
layer: 'borough'
}
}
}
}]
}
};
const view_instance = boost_sources_and_layers(config);
t.deepEquals(view_instance(), expected_query, 'query is a bool query with multiple term queres');
t.end();
});
};
module.exports.all = function (tape, common) {
function test(name, testFunction) {
return tape('boost sources and layers ' + name, testFunction);
}
for( var testCase in module.exports.tests ){
module.exports.tests[testCase](test, common);
}
};

5
test/unit/run.js

@ -64,13 +64,14 @@ var tests = [
require('./query/address_search_using_ids'), require('./query/address_search_using_ids'),
require('./query/autocomplete'), require('./query/autocomplete'),
require('./query/autocomplete_defaults'), require('./query/autocomplete_defaults'),
require('./query/search_defaults'),
require('./query/reverse_defaults'),
require('./query/reverse'), require('./query/reverse'),
require('./query/reverse_defaults'),
require('./query/search'), require('./query/search'),
require('./query/search_defaults'),
require('./query/search_original'), require('./query/search_original'),
require('./query/structured_geocoding'), require('./query/structured_geocoding'),
require('./query/text_parser'), require('./query/text_parser'),
require('./query/view/boost_sources_and_layers'),
require('./sanitizer/_boundary_country'), require('./sanitizer/_boundary_country'),
require('./sanitizer/_debug'), require('./sanitizer/_debug'),
require('./sanitizer/_flag_bool'), require('./sanitizer/_flag_bool'),

Loading…
Cancel
Save