Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

One query multiple suggesters #59

Merged
merged 5 commits into from
Jan 19, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ var controllers = {};
controllers.index = require('./controller/index');
controllers.doc = require('./controller/doc');
controllers.suggest = require('./controller/suggest');
controllers.suggest_nearby = require('./controller/suggest_nearby');
controllers.search = require('./controller/search');

/** ----------------------- routes ----------------------- **/
Expand All @@ -35,7 +34,9 @@ app.get( '/doc', sanitisers.doc.middleware, controllers.doc() );

// suggest API
app.get( '/suggest', sanitisers.suggest.middleware, controllers.suggest() );
app.get( '/suggest/nearby', sanitisers.suggest.middleware, controllers.suggest_nearby() );
app.get( '/suggest/nearby',
sanitisers.suggest.middleware,
controllers.suggest(undefined, undefined, require('./helper/queryMixer').suggest_nearby) );

// search API
app.get( '/search', sanitisers.search.middleware, controllers.search() );
Expand Down
116 changes: 20 additions & 96 deletions controller/suggest.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,46 +4,27 @@ var service = {
mget: require('../service/mget')
};
var geojsonify = require('../helper/geojsonify').search;
var async = require('async');
var resultsHelper = require('../helper/results');

function setup( backend, query ){
function setup( backend, query, query_mixer ){

// allow overriding of dependencies
backend = backend || require('../src/backend');
query = query || require('../query/suggest');
query_mixer = query_mixer || require('../helper/queryMixer').suggest;

function controller( req, res, next ){

// backend command
var cmd = {
index: 'pelias',
body: query( req.clean )
body: query( req.clean, query_mixer )
};

var SIZE = req.clean.size || 10;
var size = req.clean.size || 10;

var query_backend = function(cmd, callback) {
// query backend
service.suggest( backend, cmd, function( err, docs ){

// error handler
if( err ){ return next( err ); }

callback(null, docs);
});
};

var dedup = function(combined) {
var unique_ids = [];
return combined.filter(function(item, pos) {
if (unique_ids.indexOf(item.text) === -1) {
unique_ids.push(item.text);
return true;
}
return false;
});
};

var reply = function(docs) {
// responder
function reply( docs ){

// convert docs to geojson
var geojson = geojsonify( docs );
Expand All @@ -53,17 +34,24 @@ function setup( backend, query ){

// respond
return res.status(200).json( geojson );
};
}

var respond = function(data) {
// query backend
service.suggest( backend, cmd, function( err, suggested ){

// error handler
if( err ){ return next( err ); }

// pick the required number of results
suggested = resultsHelper.picker(suggested, size);

// no documents suggested, return empty array to avoid ActionRequestValidationException
if( !Array.isArray( data ) || !data.length ){
if( !Array.isArray( suggested ) || !suggested.length ){
return reply([]);
}

// map suggester output to mget query
var query = data.map( function( doc ) {
var query = suggested.map( function( doc ) {
var idParts = doc.text.split(':');
return {
_index: 'pelias',
Expand All @@ -81,72 +69,8 @@ function setup( backend, query ){
return reply( docs );

});
});

};

if (req.clean.input) {
var async_query;

// admin only
req.admin = {};
for (var k in req.clean) { req.admin[k] = req.clean[k]; }
req.admin.layers = ['admin0','admin1','admin2'];

if (req.clean.input.length < 4 && isNaN(parseInt(req.clean.input, 10))) {
async_query = {
admin_3p: function(callback){
cmd.body = query( req.admin, 3 );
query_backend(cmd, callback);
},
admin_1p: function(callback){
cmd.body = query( req.admin, 1 );
query_backend(cmd, callback);
},
all_3p: function(callback) {
cmd.body = query( req.clean, 3 );
query_backend(cmd, callback);
}
};
} else {
async_query = {
all_5p: function(callback){
cmd.body = query( req.clean, 5);
query_backend(cmd, callback);
},
all_3p: function(callback){
cmd.body = query( req.clean, 3);
query_backend(cmd, callback);
},
all_1p: function(callback){
cmd.body = query( req.clean, 1 );
query_backend(cmd, callback);
},
admin_1p: function(callback){
cmd.body = query( req.admin );
query_backend(cmd, callback);
}
};
}

async.parallel(async_query, function(err, results) {
// results is equal to: {a: docs, b: docs, c: docs}
var splice_length = parseInt((SIZE / Object.keys(results).length), 10);
var results_keys = Object.keys(async_query);

var combined = [];
results_keys.forEach(function(key){
combined = combined.concat(results[key].splice(0,splice_length));
});

combined = dedup(combined);
respond(combined);
});
} else {
query_backend(cmd, function(err, results) {
respond(results);
});
}

}

return controller;
Expand Down
72 changes: 0 additions & 72 deletions controller/suggest_nearby.js

This file was deleted.

28 changes: 28 additions & 0 deletions helper/queryMixer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"suggest": [
{
"layers": ["geoname","osmnode","osmway","admin0","admin1","admin2","neighborhood"],
"precision": [5, 3, 1]
},
{
"layers": ["admin0","admin1","admin2","neighborhood"],
"precision": []
},
{
"layers": ["geoname","osmnode","osmway","admin0","admin1","admin2","neighborhood"],
"precision": [3],
"fuzzy": "AUTO"
}
],
"suggest_nearby": [
{
"layers": ["geoname","osmnode","osmway","admin0","admin1","admin2","neighborhood"],
"precision": []
},
{
"layers": ["geoname","osmnode","osmway","admin0","admin1","admin2","neighborhood"],
"precision": [],
"fuzzy": "AUTO"
}
]
}
48 changes: 48 additions & 0 deletions helper/results.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@

var picker = function( results, size ){
var combined = [];
var num_results = 0;

for (var i=0; i<results.length && num_results<size; i++) {
if (results[i] && results[i].length) {
combined[i] = combined[i] || [];
combined[i].push(results[i][0]);
results[i].splice(0,1);
num_results++;
} else {
results.splice(i,1);
i--;
}

if (i === results.length-1) {
i=0;
}
}
return (combined.length > 0) ? sort_by_score(combined) : combined;
};

var dedup = function(arr) {
var unique_ids = [];
return arr.filter(function(item, pos) {
if (unique_ids.indexOf(item.name.default) === -1) {
unique_ids.push(item.name.default);
return true;
}
return false;
});
};

var sort_by_score = function(arr) {
return arr.map(function(doc) {
return doc.sort(function(a,b) {
return b.score - a.score;
});
}).reduce(function(a,b) { //flatten
return a.concat(b);
});
};

module.exports = {
picker: picker,
dedup: dedup
};
Loading