Browse Source

feat(trimByGranularity): refactor to use an index instead of multiple loops over the results

trim_by_granularity
Peter Johnson 6 years ago
parent
commit
5b4ac5da6f
  1. 55
      middleware/trimByGranularity.js

55
middleware/trimByGranularity.js

@ -43,16 +43,31 @@ function isFallbackQuery(results) {
}); });
} }
function hasRecordsAtLayers(results, layer) { // build inverted index which maps 'matched_queries' to documents
return results.some( result => { // eg. { "fallback.street": [ doc1, doc4, doc8 ] }
return result._matched_queries[0] === 'fallback.' + layer; function buildInvertedIndex(results) {
let idx = {};
results.forEach((result, ord) => {
if( _.isArray( result._matched_queries ) ){
result._matched_queries.forEach( matchedQuery => {
if( !_.isArray( idx[matchedQuery] ) ){ idx[matchedQuery] = []; }
idx[matchedQuery].push( result );
}); });
} }
function retainRecordsAtLayers(results, layer) {
return results.filter( result => {
return result._matched_queries[0] === 'fallback.' + layer;
}); });
return idx;
}
// find the most granular possible layer by working through the $layers array in
// order and returning the first one which matches the results.
// note: returns undefined on failure to match any of the layers
function findMostGranularMatchedQuery(idx) {
for( let i=0; i<layers.length; i++ ){
let matchedQueryName = 'fallback.' + layers[i];
if( _.has( idx, matchedQueryName ) ){
return matchedQueryName;
}
}
} }
function setup() { function setup() {
@ -63,17 +78,20 @@ function setup() {
return next(); return next();
} }
// start at the most granular possible layer. if there are results at a layer // build an index to avoid iterating over the data multiple times
// then remove everything not at that layer. let idx = buildInvertedIndex(res.data);
for( let i=0; i<layers.length; i++ ){
let layer = layers[i]; // find the most granular match from the layers list
if( hasRecordsAtLayers( res.data, layer ) ){ let mostGranularMatchedQuery = findMostGranularMatchedQuery(idx);
// we could not find a 'most granular match', no-op
if( !mostGranularMatchedQuery ){ return next(); }
// filter records to only contain those from target layer // remove any documents which don't have a matching fallback layer match.
let filtered = retainRecordsAtLayers(res.data, layer); let filtered = idx[mostGranularMatchedQuery];
// the filter was applied but the length remained the same // the filter was applied but the length remained the same, no-op
if( filtered.length === res.data.length ){ break; } if( filtered.length === res.data.length ){ return next(); }
// logging / debugging // logging / debugging
let logInfo = { let logInfo = {
@ -88,11 +106,6 @@ function setup() {
// update data to only contain filtered records // update data to only contain filtered records
res.data = filtered; res.data = filtered;
// stop iteration upon first successful match
break;
}
}
next(); next();
}; };
} }

Loading…
Cancel
Save