CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-flexsearch

Next-generation full-text search library for Browser and Node.js with advanced features and multi-database support

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

document-search.mddocs/

Document Search

Advanced document indexing with multi-field support, structured data handling, and field-specific search configurations. The Document class enables complex search scenarios with heterogeneous data structures and field-specific optimization.

Capabilities

Document Class

Creates a document-based search index with configurable field mapping, storage options, and indexing strategies for structured data.

/**
 * Advanced document search with multi-field indexing and structured data support
 * @param options - Document configuration with field descriptors
 */
class Document<D = DocumentData, W extends WorkerType = false, S extends StorageInterface | boolean = false, R extends boolean = true> {
  constructor(options: DocumentOptions<D, W, S, R>);
  
  /** Database connection for persistent storage */
  db: Promise<S>;
}

Adding Documents

Add structured documents with automatic field indexing and optional ID generation.

/**
 * Add structured document with explicit ID
 * @param id - Unique document identifier
 * @param document - Document object with fields to index
 * @returns Document instance or Promise for chaining
 */
add(id: Id, document: D): W extends false ? this : Promise<this>;

/**
 * Add document with auto-generated ID
 * @param document - Document object with fields to index
 * @returns Document instance or Promise for chaining
 */
add(document: D): W extends false ? this : Promise<this>;

/**
 * Append content to existing document fields
 * @param id - Document identifier
 * @param document - Additional content to append
 * @returns Document instance or Promise for chaining
 */
append(id: Id, document: D): W extends false ? this : Promise<this>;

/**
 * Update existing document content
 * @param id - Document identifier
 * @param document - Updated document content
 * @returns Document instance or Promise for chaining
 */
update(id: Id, document: D): W extends false ? this : Promise<this>;

/**
 * Remove document from all indexes and storage
 * @param id - Document identifier to remove
 * @returns Document instance or Promise for chaining
 */
remove(id: Id): W extends false ? this : Promise<this>;

Usage Examples:

import { Document } from "flexsearch";

// Create document index with field configuration
const index = new Document({
  document: {
    id: "id",
    index: ["title", "content", "tags"],
    store: ["title", "content", "author", "date"]
  }
});

// Add documents with explicit IDs
index.add(1, {
  title: "Introduction to FlexSearch",
  content: "FlexSearch is a powerful full-text search library...",
  author: "John Doe",
  tags: ["search", "javascript", "library"],
  date: "2023-01-15"
});

// Add document with auto-generated ID
index.add({
  title: "Advanced Search Techniques",
  content: "Learn how to implement complex search queries...",
  author: "Jane Smith",
  tags: ["advanced", "techniques"],
  date: "2023-02-20"
});

// Update existing document
index.update(1, {
  title: "Complete Guide to FlexSearch",
  content: "Updated comprehensive guide to FlexSearch...",
  author: "John Doe",
  tags: ["search", "javascript", "library", "guide"],
  date: "2023-01-15"
});

Document Retrieval and Storage

Retrieve complete documents and manage non-indexed storage.

/**
 * Retrieve complete document by ID from storage
 * @param id - Document identifier
 * @returns Complete document object or Promise<document>
 */
get(id: Id): S extends false ? D : Promise<D>;

/**
 * Store document without indexing (storage only)
 * @param id - Document identifier
 * @param document - Document to store
 * @returns Document instance or Promise for chaining
 */
set(id: Id, document: D): W extends false ? this : Promise<this>;

Usage Examples:

// Store document without indexing
index.set("metadata", {
  lastUpdated: "2023-03-01",
  version: "1.2.0"
});

// Retrieve complete document
const doc = index.get(1);
console.log(doc.author); // "John Doe"

Searching Documents

Search across multiple fields with field-specific options and result enrichment.

/**
 * Search across document fields with advanced options
 * @param query - Search query string or field-specific queries
 * @param options - Document search configuration
 * @returns Search results with document data
 */
search<H extends boolean = false, P extends FieldName[] = [], E extends FieldName[] = [], M extends boolean = false>(
  query: string | DocumentSearchQuery,
  options?: DocumentSearchOptions<H, P, E, M>
): DocumentSearchResults<D, W, S, R, H, P, E, M>;

/**
 * Search with caching for repeated queries
 * @param query - Search query string or field-specific queries
 * @param options - Document search configuration
 * @returns Cached search results
 */
searchCache<H extends boolean = false, P extends FieldName[] = [], E extends FieldName[] = [], M extends boolean = false>(
  query: string | DocumentSearchQuery,
  options?: DocumentSearchOptions<H, P, E, M>
): DocumentSearchResults<D, W, S, R, H, P, E, M>;

Usage Examples:

// Basic search across all indexed fields
const results = index.search("FlexSearch");

// Search specific fields with options
const titleResults = index.search("introduction", {
  index: "title",
  limit: 5
});

// Multi-field search with different queries per field
const complexResults = index.search({
  title: "guide",
  content: "search techniques",
  tags: "advanced"
});

// Search with basic highlighting
const highlighted = index.search("FlexSearch", {
  enrich: true, // Include full document data
  highlight: "<mark>|</mark>" // Simple template: open|close
});

// Advanced highlighting with all options
const advancedHighlighted = index.search("powerful search", {
  enrich: true,
  highlight: {
    template: {
      open: '<span class="highlight">',
      close: '</span>',
      separator: ' ... '
    },
    boundary: {
      before: 20,
      after: 30,
      total: 150
    },
    ellipsis: {
      template: '<span class="ellipsis">&hellip;</span>',
      pattern: true
    },
    clip: true,
    merge: true
  }
});

// Search with field plucking (return only specific fields)
const plucked = index.search("javascript", {
  pluck: ["title", "author"]
});

Tag-Based Search and Filtering

Advanced filtering using document tags and structured field values.

/**
 * Search with tag-based filtering
 * @param query - Search query
 * @param options - Search options with tag filters
 * @returns Filtered search results
 */
search(query: string, options: {
  tag?: string | string[] | TagFilterOptions;
  // ... other options
}): DocumentSearchResults<D, W, S, R>;

Usage Examples:

// Search with tag filtering
const taggedResults = index.search("search", {
  tag: "javascript" // Only return docs tagged with "javascript"
});

// Multiple tag filtering
const multiTagResults = index.search("techniques", {
  tag: ["advanced", "javascript"] // Must have both tags
});

// Complex tag filtering
const complexTagResults = index.search("guide", {
  tag: {
    include: ["guide", "tutorial"],
    exclude: ["deprecated"]
  }
});

Index Management

Check document existence, clear indexes, and manage document lifecycle.

/**
 * Check if document exists in index
 * @param id - Document identifier to check
 * @returns Boolean indicating existence or Promise<boolean>
 */
contain(id: Id): S extends false ? boolean : Promise<boolean>;

/**
 * Clear all documents from index and storage
 * @returns Document instance, void, or Promise depending on configuration
 */
clear(): W extends false ? S extends false ? this : Promise<void> : Promise<void>;

/**
 * Clean up index resources
 */
cleanup(): void;

Async Operations

Asynchronous versions of all document operations for non-blocking execution.

/**
 * Asynchronously add document
 * @param id - Document identifier
 * @param document - Document to add
 * @param callback - Optional completion callback
 * @returns Promise resolving to document instance
 */
addAsync(id: Id, document: D, callback?: AsyncCallback<void>): Promise<this>;
addAsync(document: D, callback?: AsyncCallback<void>): Promise<this>;

/**
 * Asynchronously search documents
 * @param query - Search query
 * @param options - Search configuration
 * @param callback - Optional completion callback
 * @returns Promise resolving to search results
 */
searchAsync<H, P, E, M>(
  query: string | DocumentSearchQuery,
  options?: DocumentSearchOptions<H, P, E, M>,
  callback?: AsyncCallback<DocumentSearchResults<D, W, S, R, H, P, E, M>>
): Promise<DocumentSearchResults<D, W, S, R, H, P, E, M>>;

Import & Export

Serialize and restore document indexes with full data preservation.

/**
 * Export document index data
 * @param handler - Function to handle exported data
 * @returns void or Promise<void> for async handlers
 */
export(handler: ExportHandler): void;
export(handler: ExportHandlerAsync): Promise<void>;

/**
 * Import document index data
 * @param key - Data key from export
 * @param data - Serialized data
 */
import(key: string, data: string): void;

/**
 * Serialize document index
 * @param with_function_wrapper - Include function wrapper
 * @returns Serialized index string
 */
serialize(with_function_wrapper?: boolean): SerializedFunctionString;

Persistent Storage Integration

Mount database backends for persistent document storage and indexing.

/**
 * Mount persistent storage to document index
 * @param db - Storage interface instance
 * @returns Promise resolving when mount is complete
 */
mount(db: StorageInterface): Promise<void>;

/**
 * Commit pending document changes to storage
 * @returns Promise resolving when commit is complete
 */
commit(): Promise<void>;

/**
 * Destroy persistent document index
 * @returns Promise resolving when destruction is complete
 */
destroy(): Promise<void>;

Configuration Options

DocumentOptions Interface

interface DocumentOptions<D, W, S, R> extends IndexOptions<S, R> {
  /** Document structure and field configuration */
  document: DocumentDescriptor<D>;
  /** Document alternative descriptor */
  doc?: DocumentDescriptor<D>;
  /** Worker configuration for non-blocking operations */
  worker?: WorkerType;
}

DocumentDescriptor Interface

interface DocumentDescriptor<D = DocumentData> {
  /** Document ID field name (default: "id") */
  id?: keyof D | "id";
  /** Fields to index for searching */
  index?: FieldName | FieldName[] | FieldOptions | FieldOptions[];
  /** Alternative field configuration */
  field?: FieldName | FieldName[] | FieldOptions | FieldOptions[];
  /** Tag fields for filtering */
  tag?: FieldName | FieldName[] | TagOptions | TagOptions[];
  /** Fields to store (retrieve with get()) */
  store?: FieldName | FieldName[] | StoreOptions | StoreOptions[] | boolean;
}

Field Configuration Options

interface FieldOptions extends IndexOptions {
  /** Field name to index */
  field: FieldName;
  /** Field-specific tokenization */
  tokenize?: Tokenizer;
  /** Field-specific encoding */
  encoder?: Encoders | EncoderOptions;
  /** Field-specific resolution */
  resolution?: number;
}

interface TagOptions {
  /** Tag field name */
  field: FieldName;
  /** Tag splitting configuration */
  split?: string | RegExp;
}

interface StoreOptions {
  /** Field name to store */
  field: FieldName;
  /** Store data compression */
  compress?: boolean;
}

DocumentSearchOptions Interface

interface DocumentSearchOptions<H, P, E, M> extends SearchOptions {
  /** Search specific index field(s) */
  index?: FieldName | FieldName[];
  /** Tag-based filtering */
  tag?: string | string[] | TagFilterOptions;
  /** Enable result highlighting */
  highlight?: H extends true ? HighlightOptions : never;
  /** Pluck specific fields from results */
  pluck?: P;
  /** Enrich results with full document data */
  enrich?: E;
  /** Merge results from multiple fields */
  merge?: M;
}

interface TagFilterOptions {
  /** Tags that must be present */
  include?: string | string[];
  /** Tags that must not be present */
  exclude?: string | string[];
}

/**
 * Complete highlighting configuration with advanced options
 */
type HighlightOptions = TemplateResultHighlighting | {
  /** Highlighting template configuration */
  template: TemplateResultHighlighting;
  /** Boundary configuration for context around matches */
  boundary?: HighlightBoundaryOptions | number;
  /** Ellipsis configuration for long content truncation */
  ellipsis?: HighlightEllipsisOptions | string | boolean;
  /** Enable clipping of long highlighted content */
  clip?: boolean;
  /** Enable merging of adjacent highlighted fragments */
  merge?: boolean;
};

/**
 * Template configuration for highlighting markup
 */
type TemplateResultHighlighting = string | {
  /** Opening tag for highlighted content */
  open: string;
  /** Closing tag for highlighted content */
  close: string;
  /** Template for fragment separators */
  separator?: string;
};

/**
 * Boundary options for context around highlighted matches
 */
interface HighlightBoundaryOptions {
  /** Characters to include before the match */
  before?: number;
  /** Characters to include after the match */
  after?: number;
  /** Total characters for the entire highlighted fragment */
  total?: number;
}

/**
 * Ellipsis configuration for content truncation
 */
interface HighlightEllipsisOptions {
  /** Template for ellipsis indicators */
  template: TemplateResultHighlighting;
  /** Pattern for detecting truncation points */
  pattern?: string | boolean;
}

/**
 * Tag name type for field-specific highlighting
 */
type TagName = string;

Types

type FieldName = string;
type DocumentData = { [key: string]: DocumentValue | DocumentValue[] };
type DocumentValue = string | number | boolean | null | DocumentData;

type DocumentSearchQuery = {
  [field: string]: string | SearchOptions;
};

type DocumentSearchResults<D, W, S, R, H, P, E, M> = 
  R extends false
    ? Resolver<D, W, S>
    : W extends false
      ? S extends false
        ? H extends true
          ? HighlightedResults<D, P, E>
          : P extends FieldName[]
            ? PluckedResults<D, P>
            : E extends true
              ? EnrichedResults<D>
              : Id[]
        : Promise<DocumentSearchResults<D, false, false, R, H, P, E, M>>
      : Promise<DocumentSearchResults<D, false, false, R, H, P, E, M>>;

interface HighlightedResults<D, P, E> {
  id: Id;
  highlight: { [field: string]: string[] };
  doc?: E extends true ? D : never;
}

interface PluckedResults<D, P extends FieldName[]> {
  id: Id;
  doc: Pick<D, P[number]>;
}

interface EnrichedResults<D> {
  id: Id;
  doc: D;
}

docs

document-search.md

index-search.md

index.md

persistent-storage.md

query-resolution.md

text-processing.md

worker-search.md

tile.json