Simple full-text search in your browser.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Search execution engine providing query processing, scoring, and result ranking. The search system supports both simple string queries and advanced programmatic query building with comprehensive query syntax including field restrictions, wildcards, fuzzy matching, and boolean operators.
The built search index that provides query execution capabilities.
/**
* Search index created by the Builder
*/
class Index {
/**
* Create a new Index instance (usually via Builder.build())
* @param {Object} attrs - Index attributes and configuration
*/
constructor(attrs);
/**
* Search the index using query string syntax
* @param {string} queryString - Query string with optional field restrictions, wildcards, etc.
* @returns {Array<Object>} - Array of search results with ref and score properties
*/
search(queryString);
/**
* Build queries programmatically for complex search logic
* @param {Function} builderFunction - Function that receives a Query builder instance
* @returns {Array<Object>} - Array of search results with ref and score properties
*/
query(builderFunction);
/**
* Serialize the index to JSON for storage or transmission
* @returns {Object} - Serialized index data
*/
toJSON();
/**
* Load an index from serialized JSON data
* @param {Object} serializedIndex - Previously serialized index
* @returns {lunr.Index} - Reconstructed index instance
*/
static load(serializedIndex);
}
/**
* Search result object
* @typedef {Object} SearchResult
* @property {string} ref - Document reference (as set by Builder.ref())
* @property {number} score - Relevance score (higher = more relevant)
* @property {Object} matchData - Optional match metadata and term positions
*/Usage Examples:
const lunr = require('lunr');
// Create index
const idx = lunr(function () {
this.ref('id');
this.field('title');
this.field('content');
this.add({ id: '1', title: 'JavaScript Guide', content: 'Learn JavaScript programming' });
this.add({ id: '2', title: 'Node.js Tutorial', content: 'Server-side JavaScript with Node.js' });
});
// Simple text search
const results = idx.search('javascript');
// Returns: [
// { ref: '1', score: 0.693 },
// { ref: '2', score: 0.405 }
// ]
// Field-specific search
const titleResults = idx.search('title:guide');
// Returns: [{ ref: '1', score: 1.099 }]
// Multiple terms
const multiResults = idx.search('javascript tutorial');
// Returns results containing either term, scored by relevanceComprehensive query string syntax for various search operations.
/**
* Query string syntax patterns:
*
* Simple terms: "javascript node"
* Field restrictions: "title:guide", "content:tutorial"
* Required terms: "+javascript +tutorial" (both must be present)
* Prohibited terms: "-deprecated" (must not be present)
* Wildcards: "java*" (prefix), "*script" (suffix)
* Fuzzy search: "tutorial~1" (edit distance of 1)
* Term boosting: "important^10" (boost by factor of 10)
* Grouping: "+(javascript node.js) -deprecated"
*/Usage Examples:
// Field-specific searches
idx.search('title:javascript'); // Only search in title field
idx.search('title:guide content:node'); // Search title for "guide", content for "node"
// Boolean operators
idx.search('+javascript +tutorial'); // Must contain both terms
idx.search('+javascript -deprecated'); // Must contain "javascript", must not contain "deprecated"
idx.search('javascript OR node'); // Contains either term (default behavior)
// Wildcards
idx.search('java*'); // Terms starting with "java"
idx.search('*script'); // Terms ending with "script"
idx.search('*node*'); // Terms containing "node"
// Fuzzy matching
idx.search('javascrpt~1'); // Allow 1 character difference
idx.search('tutorial~2'); // Allow up to 2 character differences
// Term boosting
idx.search('javascript^10 tutorial'); // Boost "javascript" by factor of 10
idx.search('title:guide^5 content:node'); // Boost title matches
// Complex queries
idx.search('+(title:javascript^10 content:node) -deprecated~1');Advanced programmatic query building for complex search logic.
/**
* Programmatic query building through the query() method
* @param {Function} builderFunction - Function that receives a Query builder
*/
Index.prototype.query;Usage Examples:
// Programmatic query building
const results = idx.query(function (q) {
// Add required term
q.term('javascript', {
presence: lunr.Query.presence.REQUIRED,
boost: 10
});
// Add optional field-specific term
q.term('tutorial', {
fields: ['title'],
presence: lunr.Query.presence.OPTIONAL,
boost: 5
});
// Add prohibited term
q.term('deprecated', {
presence: lunr.Query.presence.PROHIBITED
});
});
// Wildcard queries
const wildcardResults = idx.query(function (q) {
q.term('java', {
wildcard: lunr.Query.wildcard.TRAILING, // "java*"
boost: 2
});
});
// Fuzzy queries with edit distance
const fuzzyResults = idx.query(function (q) {
q.term('javascrpt', {
editDistance: 1,
boost: 0.5 // Lower boost for fuzzy matches
});
});Saving and loading indexes for persistent storage or network transmission.
/**
* Serialize index to JSON
* @returns {Object} - Serialized index data
*/
Index.prototype.toJSON;
/**
* Load index from serialized data
* @param {Object} serializedIndex - Previously serialized index
* @returns {lunr.Index} - Reconstructed index instance
*/
Index.load;Usage Examples:
// Serialize index for storage
const idx = lunr(function () {
this.ref('id');
this.field('content');
this.add({ id: '1', content: 'Searchable content' });
});
const serialized = idx.toJSON();
// Save to localStorage
localStorage.setItem('searchIndex', JSON.stringify(serialized));
// Save to file (Node.js)
const fs = require('fs');
fs.writeFileSync('index.json', JSON.stringify(serialized));
// Load from storage
const storedData = JSON.parse(localStorage.getItem('searchIndex'));
const loadedIdx = lunr.Index.load(storedData);
// Load from file (Node.js)
const fileData = JSON.parse(fs.readFileSync('index.json', 'utf8'));
const fileIdx = lunr.Index.load(fileData);
// Use loaded index normally
const results = loadedIdx.search('searchable');/**
* Individual search result
* @typedef {Object} SearchResult
* @property {string} ref - Document reference identifier
* @property {number} score - Relevance score (0.0 to ~4.0+, higher = more relevant)
* @property {lunr.MatchData} matchData - Detailed match information (if available)
*/
/**
* Match data providing detailed information about matches
* @typedef {Object} MatchData
* @property {Object} metadata - Term metadata including positions and frequencies
*/Usage Examples:
const results = idx.search('javascript tutorial');
results.forEach(result => {
console.log(`Document: ${result.ref}`);
console.log(`Score: ${result.score.toFixed(3)}`);
if (result.matchData) {
// Access detailed match information
const metadata = result.matchData.metadata;
Object.keys(metadata).forEach(term => {
console.log(`Term "${term}" found in:`, Object.keys(metadata[term]));
});
}
});Understanding and working with Lunr's BM25-based scoring system.
// Results are already sorted by score (highest first)
const results = idx.search('query terms');
// Custom result processing
const processedResults = results
.filter(result => result.score > 0.5) // Filter by minimum score
.slice(0, 10) // Limit to top 10
.map(result => ({
...result,
normalizedScore: Math.min(result.score / 2.0, 1.0) // Normalize score to 0-1
}));
// Group results by score ranges
const groupedResults = {
high: results.filter(r => r.score > 1.5),
medium: results.filter(r => r.score > 0.5 && r.score <= 1.5),
low: results.filter(r => r.score <= 0.5)
};// Search across multiple fields with different weights
const results = idx.query(function (q) {
const searchTerm = 'javascript';
// High weight for title matches
q.term(searchTerm, {
fields: ['title'],
boost: 10
});
// Medium weight for content matches
q.term(searchTerm, {
fields: ['content'],
boost: 5
});
// Low weight for tag matches
q.term(searchTerm, {
fields: ['tags'],
boost: 2
});
});// Implement auto-complete functionality
function autoComplete(partialTerm, maxResults = 5) {
return idx.query(function (q) {
// Add wildcard for prefix matching
q.term(partialTerm, {
wildcard: lunr.Query.wildcard.TRAILING,
boost: 10
});
// Also add fuzzy matching for typos
q.term(partialTerm, {
editDistance: 1,
boost: 5
});
}).slice(0, maxResults);
}
const suggestions = autoComplete('java'); // Finds "javascript", "java", etc.// Combine field restrictions for faceted search
function facetedSearch(query, facets = {}) {
return idx.query(function (q) {
// Main search term
if (query) {
q.term(query, { boost: 10 });
}
// Apply facet filters
Object.entries(facets).forEach(([field, value]) => {
q.term(value, {
fields: [field],
presence: lunr.Query.presence.REQUIRED
});
});
});
}
// Search for "tutorial" in documents tagged as "beginner" with category "javascript"
const facetedResults = facetedSearch('tutorial', {
tags: 'beginner',
category: 'javascript'
});