Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
missinglink committed Sep 4, 2015
0 parents commit 63f77e5
Show file tree
Hide file tree
Showing 19 changed files with 1,055 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .gitignore
@@ -0,0 +1,5 @@
node_modules
coverage
.idea
*.log
reports
75 changes: 75 additions & 0 deletions defaults.json
@@ -0,0 +1,75 @@
{
"size": 10,
"track_scores": true,

"centroid:field": "center_point",

"boundary:circle:radius": "50km",
"boundary:circle:distance_type": "plane",
"boundary:circle:optimize_bbox": "indexed",
"boundary:circle:_cache": true,

"boundary:rect:type": "indexed",
"boundary:rect:_cache": true,

"ngram:analyzer": "peliasOneEdgeGram",
"ngram:field": "name.default",
"ngram:boost": 1,

"phrase:analyzer": "peliasPhrase",
"phrase:field": "phrase.default",
"phrase:boost": 1,
"phrase:slop": 2,

"focus:function": "linear",
"focus:offset": "1km",
"focus:scale": "50km",
"focus:decay": 0.5,

"function_score:score_mode": "avg",
"function_score:boost_mode": "replace",

"address:housenumber:analyzer": "standard",
"address:housenumber:field": "address.number",
"address:housenumber:boost": 1,

"address:street:analyzer": "standard",
"address:street:field": "address.street",
"address:street:boost": 1,

"address:postcode:analyzer": "standard",
"address:postcode:field": "address.zip",
"address:postcode:boost": 1,

"admin:alpha3:analyzer": "standard",
"admin:alpha3:field": "alpha3",
"admin:alpha3:boost": 1,

"admin:admin0:analyzer": "peliasAdmin",
"admin:admin0:field": "admin0",
"admin:admin0:boost": 1,

"admin:admin1:analyzer": "peliasAdmin",
"admin:admin1:field": "admin1",
"admin:admin1:boost": 1,

"admin:admin1_abbr:analyzer": "peliasAdmin",
"admin:admin1_abbr:field": "admin1_abbr",
"admin:admin1_abbr:boost": 1,

"admin:admin2:analyzer": "peliasAdmin",
"admin:admin2:field": "admin2",
"admin:admin2:boost": 1,

"admin:local_admin:analyzer": "peliasAdmin",
"admin:local_admin:field": "local_admin",
"admin:local_admin:boost": 1,

"admin:locality:analyzer": "peliasAdmin",
"admin:locality:field": "locality",
"admin:locality:boost": 1,

"admin:neighborhood:analyzer": "peliasAdmin",
"admin:neighborhood:field": "neighborhood",
"admin:neighborhood:boost": 1
}
86 changes: 86 additions & 0 deletions example.js
@@ -0,0 +1,86 @@

var query = require('./index');
var defaults = require('./defaults');

/**
=== input params ===
input:name: 'hackney city farm'
focus.point.lat: 1.1
focus.point.lon: 2.2
input.housenumber: 101
input.street: "hackney road"
input.postcode: "E81DN"
input:admin:alpha3: "GBR"
input:admin:admin0: "hackney"
input:admin:admin1: "hackney"
input:admin:admin1_abbr: "hackney"
input:admin:admin2: "hackney"
input:admin:local_admin: "hackney"
input:admin:locality: "hackney"
input:admin:neighborhood: "hackney"
boundary:circle:lat: 1
boundary:circle:lon: 2
boundary:circle:radius: "50km"
boundary.rect.top: 1
boundary.rect.right: 2
boundary.rect.bottom: 2
boundary.rect.left: 1
boundary.country: "USA"
**/

var vs = new query.Vars( defaults );
var q = new query.layout.FilteredBooleanQuery();

vs.var( 'input:name','hackney city farm' );
vs.set({ 'focus.point.lat': 1, 'focus.point.lon': 2 });
vs.set({ 'input:housenumber': 1, 'input:street': 'foo street' });
vs.set({ 'boundary:circle:lat': 1, 'boundary:circle:lon': 2 });

vs.set({
'boundary:rect:top': 1,
'boundary:rect:right': 2,
'boundary:rect:bottom': 2,
'boundary:rect:left': 2
});

vs.set({
'boundary:country': 'USA'
});

// mandatory matches
q.score( query.view.boundary_country, 'must' )
.score( query.view.ngrams, 'must' );

// scoring boost
q.score( query.view.phrase )
.score( query.view.focus );

// address components
q.score( query.view.address('housenumber') )
.score( query.view.address('street') )
.score( query.view.address('postcode') );

// admin components
q.score( query.view.admin('alpha3') )
.score( query.view.admin('admin0') )
.score( query.view.admin('admin1') )
.score( query.view.admin('admin1_abbr') )
.score( query.view.admin('admin2') )
.score( query.view.admin('local_admin') )
.score( query.view.admin('locality') )
.score( query.view.admin('neighborhood') );

// non-scoring hard filters
q.filter( query.view.boundary_circle )
.filter( query.view.boundary_rect );

var rendered = q.render( vs );

console.log( JSON.stringify( rendered, null, 2 ) );
17 changes: 17 additions & 0 deletions index.js
@@ -0,0 +1,17 @@

module.exports.Vars = require('./lib/VariableStore');

module.exports.layout = {
FilteredBooleanQuery: require('./layout/FilteredBooleanQuery')
};

module.exports.view = {
focus: require('./view/focus'),
ngrams: require('./view/ngrams'),
phrase: require('./view/phrase'),
address: require('./view/address'),
admin: require('./view/admin'),
boundary_circle: require('./view/boundary_circle'),
boundary_rect: require('./view/boundary_rect'),
boundary_country: require('./view/boundary_country')
};
68 changes: 68 additions & 0 deletions layout/FilteredBooleanQuery.js
@@ -0,0 +1,68 @@

function Layout(){
this._score = [];
this._filter = [];
}

Layout.prototype.score = function( view, operator ){
this._score.push([ view, operator === 'must' ? 'must': 'should' ]);
return this;
};

Layout.prototype.filter = function( view, operator ){
this._score.push([ view, operator === 'must' ? 'must': 'should' ]);
return this;
};

Layout.prototype.render = function( vs ){
var q = Layout.base( vs );

// handle scoring views under 'query' section (both must & should)
if( this._score.length ){
this._score.forEach( function( condition ){
var view = condition[0], operator = condition[1];
if( !q.query.filtered.query.bool.hasOwnProperty( operator ) ){
q.query.filtered.query.bool[ operator ] = [];
}
var rendered = view( vs );
if( rendered ){
q.query.filtered.query.bool[ operator ].push( rendered );
}
});
}

// handle filter views under 'filter' section (only must)
if( this._filter.length ){
this._filter.forEach( function( condition ){
var view = condition[0], operator = condition[1];
if( !q.query.filtered.filter.bool.hasOwnProperty( operator ) ){
q.query.filtered.filter.bool[ operator ] = [];
}
var rendered = view( vs );
if( rendered ){
q.query.filtered.filter.bool[ operator ].push( rendered );
}
});
}

return q;
};

Layout.base = function( vs ){
return {
query: {
filtered: {
query: {
bool: {}
},
filter: {
bool: {}
}
}
},
size: vs.var('size'),
track_scores: vs.var('track_scores')
};
};

module.exports = Layout;
36 changes: 36 additions & 0 deletions lib/Variable.js
@@ -0,0 +1,36 @@

/**
A primative javascript variable wrapped in an Object so that it can be
handled by reference instead of by value.
This is useful as an inline variable placeholder where the value may or
may not be known when the query is constructed.
note: values must be a valid js primative type (string,numeric,boolean)
note: the object prototype contains custom seliazation methods
warning: using an instance of Variable() in a boolean operation will
*always* yeild true; regardless of the underlying value; because js.
**/

var check = require('check-types');

function Variable(){
this.$ = '';
}

Variable.prototype.set = function( val ){
if( !check.unemptyString(val) && !check.number(val) && !check.boolean(val) ){
throw new Error( 'invalid value, value must be valid js Variable' );
}
this.$ = val;
};

Variable.prototype.valueOf =
Variable.prototype.toString =
Variable.prototype.toJSON =
Variable.prototype.get = function(){
return this.$;
};

module.exports = Variable;

0 comments on commit 63f77e5

Please sign in to comment.