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

Fuzziness #41

Closed
wants to merge 13 commits into from
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
165 changes: 38 additions & 127 deletions controller/suggest.js
Original file line number Diff line number Diff line change
@@ -1,151 +1,62 @@

var service = {
suggest: require('../service/suggest'),
mget: require('../service/mget')
};
var geojsonify = require('../helper/geojsonify').search;
var helper = require('../helper/suggest');
var async = require('async');

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 ){
var suggest = helper(backend, res, next);

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

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) {

// convert docs to geojson
var geojson = geojsonify( docs );

// response envelope
geojson.date = new Date().getTime();

// respond
return res.status(200).json( geojson );
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'];

// build async query
var add_async_query = function(index, layers, precision, fuzzy) {
async_query['index_' + index] = function(callback) {
cmd.body = query( layers, precision, fuzzy );
suggest.query_backend(cmd, callback);
};
};

var respond = function(data) {

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

// map suggester output to mget query
var query = data.map( function( doc ) {
var idParts = doc.text.split(':');
return {
_index: 'pelias',
_type: idParts[0],
_id: idParts.slice(1).join(':')
};
});

service.mget( backend, query, function( err, docs ){

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

// reply
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);
}
};

query_mixer.forEach(function(item, index){
var layers = item.layers === 'admin' ? req.admin : req.clean;
if (item.precision && Array.isArray( item.precision ) && item.precision.length ) {
item.precision.forEach(function(precision) {
add_async_query(index+'.'+precision, layers, precision, item.fuzzy);
});
} 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);
}
};
add_async_query(index, layers, undefined, item.fuzzy);
}
});

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);

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);
var combined = [];
results_keys.forEach(function(key){
combined = combined.concat(suggest.sort_by_score(results[key]).splice(0,splice_length));
});
}

combined = suggest.dedup(combined);
suggest.respond(combined);
});

}

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": "all",
"precision": [5, 3, 1]
},
{
"layers": "admin",
"precision": []
},
{
"layers": "all",
"precision": [3],
"fuzzy": "AUTO"
}
],
"suggest_nearby": [
{
"layers": "all",
"precision": []
},
{
"layers": "all",
"precision": [],
"fuzzy": "AUTO"
}
]
}
Loading