or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

document-search.mdindex-search.mdindex.mdpersistent-storage.mdquery-resolution.mdtext-processing.mdworker-search.md
tile.json

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;
}