inquery
Version:
A portable indexing and searching library.
128 lines (79 loc) • 2.3 kB
JavaScript
const BM25 = require( '@spacebartech/bm25' );
const Globals = require( './globals' );
const HasProperty = function ( a, b ) {
return Object.prototype.hasOwnProperty.call( a, b );
};
class Inquery {
constructor() {
this.index = new BM25();
}
search( query ) {
if ( !query ) {
return [];
}
const searchTerms = query.split( /\ +/ ); // eslint-disable-line
const stripStopWords = ( searchTerms.length > 2 );
const tokenizedTerms = this.index.tokenize( query, stripStopWords );
const tokens = [];
const documentTokens = Object.keys( this.index.terms );
const terms = this.index.terms;
tokenizedTerms.forEach( ( term ) => {
// find perfect match
if ( HasProperty( terms, term ) ) {
tokens.push( {
term,
relevance : 3,
} );
}
// find match of substring
documentTokens.forEach( ( token ) => {
const longest = token.length > term.length ? token : term;
const shortest = longest === token ? term : token;
const match = Globals.findMatch( term, token );
if ( match !== -1 ) {
tokens.push( {
term : token,
relevance : shortest.length / ( shortest.length + match ),
} );
}
} );
} );
const documents = this.index.documents; // eslint-disable-line
const addedIn = {};
const results = [];
tokens.forEach( ( token ) => {
const term = this.index.terms[token.term];
term.foundIn.forEach( ( id ) => {
if ( HasProperty( addedIn, id ) ) {
// decrease the relevance of the token
if ( token.relevance < 1 ) {
token.relevance *= token.relevance; // eslint-disable-line
}
// add this decreased value to the total
// sum of all relevance in results
const docIndex = addedIn[id];
results[docIndex].relevance += token.relevance;
}
else {
// otherwise, make a note of where it is in
// the results array
addedIn[id] = results.length;
const result = {
relevance : token.relevance,
document : documents[id],
id
};
results.push( result );
}
} );
} );
return results;
}
addDocument( document, key ) {
this.index.addDocument( document, key );
}
getIndex() {
return this.index.terms;
}
}
module.exports = Inquery;