mfsearch
Version:
Indexed search for MasterFormat-style datasets
77 lines (69 loc) • 2.42 kB
JavaScript
const _ = require('lodash');
const {
Search, SimpleTokenizer,
StemmingTokenizer,
UnorderedSearchIndex,
} = require('js-search');
const { stemmer } = require('porter-stemmer');
class MFSearch {
//
// by default, exclude all of divisions 40-46, 34, and 35
constructor({ mfData, subsetRE = /^(?!(34|35|4[0123456]))/ }) {
this.searchData = _.map(_.filter(mfData, (item) => {
return item.code.match(subsetRE);
}), (item, idx) => {
return {
code: item.code,
level: item.level,
description: item.description,
primaryText: `${item.code} ${item.description}`,
key: idx,
};
});
const { stemmer } = require('porter-stemmer');
this.search = new Search('description');
this.search.tokenizer = new StemmingTokenizer(stemmer, new SimpleTokenizer());
this.search.searchIndex = new UnorderedSearchIndex();
this.search.addIndex('description');
this.search.addIndex('code');
this.search.addDocuments(this.searchData);
}
//
// Full scan of search dataset
locate ({ filterText = undefined, codePrefix = undefined, level = undefined }) {
let ret;
if (_.isUndefined(filterText)) {
ret = this.searchData;
} else {
ret = this.search.search(filterText);
}
if (!_.isUndefined(level)) {
ret = _.filter(ret, (item) => { return item.level == level; });
}
if (!_.isUndefined(codePrefix)) {
ret = _.filter(ret, (item) => { return _.startsWith(item.code, codePrefix); });
}
return ret;
};
//
// Return division (Level 1) items, optionally filtered.
divisions ({ filterText = undefined }) {
return this.locate({ filterText, level: 1 });
}
//
// Return group (Level 2) items within specified division, optionally filtered.
groupsOfDivision ({ filterText = undefined, divisionCode = '' }) {
return this.locate({ filterText, codePrefix: divisionCode.substring(0,2), level: 2});
}
//
// Return Level 3 items within specified division, optionally filtered.
lineItemsOfGroup ({ filterText = undefined, groupCode = '' }) {
return this.locate({ filterText, codePrefix: groupCode.substring(0,3), level: 3 });
}
}
const codeStem = ({ code, level=1 }) => {
const stemLength = level+1;
if (level<1 || level>3 || code.length < stemLength ) return code;
return code.substring(0,stemLength);
};
module.exports = { MFSearch, codeStem };