UNPKG

inquery

Version:

A portable indexing and searching library.

128 lines (79 loc) 2.3 kB
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;