Browse Source

add a view to boost exact matches

pull/529/head
missinglink 9 years ago
parent
commit
01a3233a7b
  1. 2
      package.json
  2. 4
      query/autocomplete.js
  3. 48
      query/view/boost_exact_matches.js
  4. 14
      test/unit/fixture/autocomplete_linguistic_multiple_tokens.js
  5. 11
      test/unit/fixture/autocomplete_linguistic_with_admin.js
  6. 147
      test/unit/fixture/autocomplete_single_character_street.js
  7. 17
      test/unit/query/autocomplete.js

2
package.json

@ -68,7 +68,7 @@
"precommit-hook": "^3.0.0",
"proxyquire": "^1.4.0",
"tap-dot": "1.0.5",
"tape": "^4.4.0"
"tape": "^4.5.1"
},
"pre-commit": [
"lint",

4
query/autocomplete.js

@ -10,7 +10,8 @@ var views = {
focus_selected_layers: require('./view/focus_selected_layers'),
ngrams_last_token_only: require('./view/ngrams_last_token_only'),
phrase_first_tokens_only: require('./view/phrase_first_tokens_only'),
pop_subquery: require('./view/pop_subquery')
pop_subquery: require('./view/pop_subquery'),
boost_exact_matches: require('./view/boost_exact_matches')
};
//------------------------------
@ -38,6 +39,7 @@ query.score( peliasQuery.view.admin('locality') );
query.score( peliasQuery.view.admin('neighbourhood') );
// scoring boost
query.score( views.boost_exact_matches );
query.score( views.focus_selected_layers( views.ngrams_strict ) );
query.score( peliasQuery.view.popularity( views.pop_subquery ) );
query.score( peliasQuery.view.population( views.pop_subquery ) );

48
query/view/boost_exact_matches.js

@ -0,0 +1,48 @@
var peliasQuery = require('pelias-query'),
searchDefaults = require('../search_defaults');
/**
This view (unfortunately) requires autocomplete to use the phrase.* index.
ideally we wouldn't need to use this, but at time of writing we are unable
to distinguish between 'complete tokens' and 'grams' in the name.* index.
this view was introduced in order to score exact matches higher than partial
matches, without it we find results such as "Clayton Avenue" appearing first
in the results list for the query "Clay Av".
the view uses some of the values from the 'search_defaults.js' file to add an
additional 'SHOULD' condition which scores exact matches slighly higher
than partial matches.
**/
module.exports = function( vs ){
// make a copy of the variables so we don't interfere with the values
// passed to other views.
var vsCopy = new peliasQuery.Vars( vs.export() );
// copy phrase:* values from search defaults
vsCopy.var('phrase:analyzer').set(searchDefaults['phrase:analyzer']);
vsCopy.var('phrase:field').set(searchDefaults['phrase:field']);
// split the 'input:name' on whitespace
var name = vs.var('input:name').get(),
tokens = name.split(' ');
// if the query is incomplete then we need to remove
// the final (incomplete) token as it will not match
// tokens in the phrase.* index.
if( !vs.var('input:name:isComplete').get() ){
tokens.pop();
}
// no valid tokens to use, fail now, don't render this view.
if( tokens.length < 1 ){ return null; }
// set 'input:name' to be only the fully completed characters
vsCopy.var('input:name').set( tokens.join(' ') );
return peliasQuery.view.phrase( vsCopy );
};

14
test/unit/fixture/autocomplete_linguistic_multiple_tokens.js

@ -26,7 +26,19 @@ module.exports = {
}
}
}],
'should':[{
'should':[
{
'match': {
'phrase.default': {
'analyzer' : 'peliasPhrase',
'type' : 'phrase',
'boost' : 1,
'slop' : 3,
'query' : 'one two'
}
}
},
{
'function_score': {
'query': {
'match': {

11
test/unit/fixture/autocomplete_linguistic_with_admin.js

@ -81,6 +81,17 @@ module.exports = {
}
}
},
{
'match': {
'phrase.default': {
'analyzer' : 'peliasPhrase',
'type' : 'phrase',
'boost' : 1,
'slop' : 3,
'query' : 'one two'
}
}
},
{
'function_score': {
'query': {

147
test/unit/fixture/autocomplete_single_character_street.js

@ -0,0 +1,147 @@
module.exports = {
'query': {
'filtered': {
'query': {
'bool': {
'must': [{
'match': {
'name.default': {
'analyzer': 'peliasQueryFullToken',
'type': 'phrase',
'boost': 1,
'slop': 3,
'query': 'k road'
}
}
}],
'should':[
{
'match': {
'address_parts.street': {
'query': 'k road',
'boost': 5,
'analyzer': 'peliasStreet'
}
}
}, {
'match': {
'parent.country': {
'query': 'laird',
'boost': 800,
'analyzer': 'peliasAdmin'
}
}
}, {
'match': {
'parent.region': {
'query': 'laird',
'boost': 600,
'analyzer': 'peliasAdmin'
}
}
}, {
'match': {
'parent.region_a': {
'query': 'laird',
'boost': 600,
'analyzer': 'peliasAdmin'
}
}
}, {
'match': {
'parent.county': {
'query': 'laird',
'boost': 400,
'analyzer': 'peliasAdmin'
}
}
}, {
'match': {
'parent.localadmin': {
'query': 'laird',
'boost': 200,
'analyzer': 'peliasAdmin'
}
}
}, {
'match': {
'parent.locality': {
'query': 'laird',
'boost': 200,
'analyzer': 'peliasAdmin'
}
}
}, {
'match': {
'parent.neighbourhood': {
'query': 'laird',
'boost': 200,
'analyzer': 'peliasAdmin'
}
}
},
{
'match': {
'phrase.default': {
'analyzer' : 'peliasPhrase',
'type' : 'phrase',
'boost' : 1,
'slop' : 3,
'query' : 'k road'
}
}
},
{
'function_score': {
'query': {
'match': {
'name.default': {
'analyzer': 'peliasQueryFullToken',
'query': 'k road',
}
}
},
'max_boost': 20,
'score_mode': 'first',
'boost_mode': 'replace',
'functions': [{
'field_value_factor': {
'modifier': 'log1p',
'field': 'popularity',
'missing': 1
},
'weight': 1
}]
}
},{
'function_score': {
'query': {
'match': {
'name.default': {
'analyzer': 'peliasQueryFullToken',
'query': 'k road',
}
}
},
'max_boost': 20,
'score_mode': 'first',
'boost_mode': 'replace',
'functions': [{
'field_value_factor': {
'modifier': 'log1p',
'field': 'population',
'missing': 1
},
'weight': 3
}]
}
}]
}
}
}
},
'sort': [ '_score' ],
'size': 20,
'track_scores': true
};

17
test/unit/query/autocomplete.js

@ -107,6 +107,23 @@ module.exports.tests.query = function(test, common) {
t.deepEqual(compiled, expected, 'valid autocomplete query with source filtering');
t.end();
});
test('single character street address', function(t) {
var query = generate({
text: 'k road, laird',
parsed_text: {
name: 'k road',
street: 'k road',
regions: [ 'laird' ]
}
});
var compiled = JSON.parse( JSON.stringify( query ) );
var expected = require('../fixture/autocomplete_single_character_street');
t.deepEqual(compiled, expected, 'autocomplete_single_character_street');
t.end();
});
};
module.exports.all = function (tape, common) {

Loading…
Cancel
Save