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

query-resolution.mddocs/

Query Resolution

Advanced query resolution system for complex boolean operations and result manipulation. The Resolver class enables sophisticated search scenarios requiring logical operations, result boosting, and custom scoring algorithms.

Capabilities

Resolver Class

Advanced query resolver that processes intermediate search results and applies boolean logic operations.

/**
 * Advanced query resolver for complex search operations and boolean logic
 * @param options - Resolver configuration options or initial search results
 */
class Resolver<
  D extends DocumentData = undefined,
  W extends WorkerType = false, 
  S extends StorageInterface | boolean = false,
  H extends HighlightOptions | boolean = false,
  R extends boolean = false,
  E extends boolean = H extends false ? false : true,
  A extends boolean = false
> {
  constructor(options?: ResolverOptions<D, W, S, H, R, E, A> | IntermediateSearchResults);
  
  /** Current intermediate search results */
  result: IntermediateSearchResults;
}

Boolean Operations

Perform logical operations on search results to create complex query combinations.

/**
 * Perform AND operation on search results (intersection)
 * @param args - Search results or queries to intersect
 * @returns Resolver instance for chaining with proper type propagation
 */
and<
  d extends DocumentData = D,
  h extends HighlightOptions | boolean = H,
  r extends boolean = R,
  e extends boolean = h extends HighlightOptions ? true : E,
  a extends boolean = A
>(...args: ResolverOptions<d, W, S, h, r, e, a>[]):
  DocumentSearchResultsWrapper<d, W, S, h, true, r, e, false, a>;

/**
 * Perform OR operation on search results (union)
 * @param args - Search results or queries to combine
 * @returns Resolver instance for chaining with proper type propagation
 */
or<
  d extends DocumentData = D,
  h extends HighlightOptions | boolean = H,
  r extends boolean = R,
  e extends boolean = h extends HighlightOptions ? true : E,
  a extends boolean = A
>(...args: ResolverOptions<d, W, S, h, r, e, a>[]):
  DocumentSearchResultsWrapper<d, W, S, h, true, r, e, false, a>;

/**
 * Perform XOR operation on search results (exclusive or)
 * @param args - Search results or queries for exclusive combination
 * @returns Resolver instance for chaining with proper type propagation
 */
xor<
  d extends DocumentData = D,
  h extends HighlightOptions | boolean = H,
  r extends boolean = R,
  e extends boolean = h extends HighlightOptions ? true : E,
  a extends boolean = A
>(...args: ResolverOptions<d, W, S, h, r, e, a>[]):
  DocumentSearchResultsWrapper<d, W, S, h, true, r, e, false, a>;

/**
 * Perform NOT operation on search results (exclusion)
 * @param args - Search results or queries to exclude
 * @returns Resolver instance for chaining with proper type propagation
 */
not<
  d extends DocumentData = D,
  h extends HighlightOptions | boolean = H,
  r extends boolean = R,
  e extends boolean = h extends HighlightOptions ? true : E,
  a extends boolean = A
>(...args: ResolverOptions<d, W, S, h, r, e, a>[]):
  DocumentSearchResultsWrapper<d, W, S, h, true, r, e, false, a>;

Usage Examples:

import { Index, Resolver } from "flexsearch";

// Create multiple indexes for different content types
const titleIndex = new Index();
const contentIndex = new Index();
const tagIndex = new Index();

// Add content to indexes
titleIndex.add(1, "JavaScript Programming Guide");
titleIndex.add(2, "Python Web Development");
titleIndex.add(3, "JavaScript Framework Comparison");

contentIndex.add(1, "Learn JavaScript fundamentals and advanced concepts");
contentIndex.add(2, "Build web applications with Python and Django");
contentIndex.add(3, "React vs Vue vs Angular framework analysis");

tagIndex.add(1, "javascript programming tutorial");
tagIndex.add(2, "python web backend");
tagIndex.add(3, "javascript frontend frameworks");

// Search each index
const titleResults = titleIndex.search("javascript");
const contentResults = contentIndex.search("javascript");
const tagResults = tagIndex.search("javascript");

// Create resolver with boolean operations
const resolver = new Resolver()
  .and(titleResults, contentResults)  // Must match in both title AND content
  .or(tagResults);                    // OR match in tags

const finalResults = resolver.resolve();
console.log(finalResults); // [1, 3] - documents matching the complex query

Result Processing

Apply result manipulation operations like limiting, offsetting, and boosting.

/**
 * Limit the number of results returned
 * @param limit - Maximum number of results to return
 * @returns Resolver instance for chaining
 */
limit(limit: number): Resolver<D, W, S>;

/**
 * Set offset for result pagination
 * @param offset - Number of results to skip
 * @returns Resolver instance for chaining
 */
offset(offset: number): Resolver<D, W, S>;

/**
 * Apply boosting to search results
 * @param boost - Boost factor for result scoring
 * @returns Resolver instance for chaining
 */
boost(boost: number): Resolver<D, W, S>;

Usage Examples:

// Complex query with result processing
const resolver = new Resolver()
  .and(titleResults, contentResults)
  .not(excludedResults)
  .boost(1.5)      // Boost relevance scores
  .limit(10)       // Return max 10 results
  .offset(0);      // Start from first result

const results = resolver.resolve();

Result Resolution

Finalize and resolve the query results with optional configuration.

/**
 * Resolve final results from the query operations
 * @param options - Resolution configuration options
 * @returns Final resolved results with proper typing
 */
resolve<
  h extends HighlightOptions | boolean = H,
  e extends boolean = h extends HighlightOptions ? true : E,
  a extends boolean = A
>(options?: DefaultResolve<D, h, true, e>):
  DocumentSearchResultsWrapper<D, W, S, h, true, true, e, false, a>;

Usage Examples:

// Basic resolution
const basicResults = resolver.resolve();

// Resolution with options
const detailedResults = resolver.resolve({
  includeScores: true,
  sortBy: "relevance",
  format: "detailed"
});

Advanced Query Patterns

Complex query combinations using multiple boolean operations and intermediate resolvers.

Usage Examples:

// Complex multi-field search with boolean logic
const searchTerm = "javascript";
const excludeTerm = "deprecated";

// Search multiple fields
const titleResults = titleIndex.search(searchTerm);
const contentResults = contentIndex.search(searchTerm);
const authorResults = authorIndex.search("expert");
const excludeResults = contentIndex.search(excludeTerm);

// Build complex query: (title OR content) AND author AND NOT deprecated
const complexResolver = new Resolver()
  .or(titleResults, contentResults)  // Match in title OR content
  .and(authorResults)                // AND written by expert authors
  .not(excludeResults);              // BUT NOT deprecated content

const finalResults = complexResolver
  .boost(1.2)
  .limit(20)
  .resolve();

console.log("Complex search results:", finalResults);

Nested Query Resolution

Use resolvers within other resolvers for highly complex query structures.

Usage Examples:

// Create sub-queries
const techResolver = new Resolver()
  .or(
    titleIndex.search("javascript"),
    titleIndex.search("python"),
    titleIndex.search("java")
  );

const levelResolver = new Resolver()
  .or(
    contentIndex.search("beginner"),
    contentIndex.search("intermediate")
  );

const typeResolver = new Resolver()
  .and(
    tagIndex.search("tutorial"),
    tagIndex.search("guide")
  );

// Combine sub-queries
const masterResolver = new Resolver()
  .and(techResolver.resolve())     // Must match tech terms
  .and(levelResolver.resolve())    // AND match difficulty level
  .or(typeResolver.resolve())      // OR match content type
  .not(contentIndex.search("deprecated"));

const results = masterResolver
  .boost(1.5)
  .limit(15)
  .resolve();

Conditional Query Building

Build queries dynamically based on conditions and user preferences.

Usage Examples:

function buildSearchQuery(params) {
  const resolver = new Resolver();
  
  // Base search across multiple fields
  if (params.query) {
    const titleResults = titleIndex.search(params.query);
    const contentResults = contentIndex.search(params.query);
    resolver.or(titleResults, contentResults);
  }
  
  // Add category filter if specified
  if (params.category) {
    const categoryResults = categoryIndex.search(params.category);
    resolver.and(categoryResults);
  }
  
  // Add author filter if specified
  if (params.author) {
    const authorResults = authorIndex.search(params.author);
    resolver.and(authorResults);
  }
  
  // Exclude certain content types
  if (params.excludeTypes && params.excludeTypes.length > 0) {
    params.excludeTypes.forEach(type => {
      const excludeResults = typeIndex.search(type);
      resolver.not(excludeResults);
    });
  }
  
  // Apply pagination and boosting
  return resolver
    .boost(params.boost || 1.0)
    .limit(params.limit || 20)
    .offset(params.offset || 0)
    .resolve();
}

// Use dynamic query builder
const searchResults = buildSearchQuery({
  query: "web development",
  category: "programming",
  excludeTypes: ["archived", "draft"],
  boost: 1.3,
  limit: 10
});

Result Scoring and Ranking

Custom scoring algorithms and result ranking with the Resolver.

Usage Examples:

// Multiple search criteria with different weights
const primaryResults = titleIndex.search("important topic");
const secondaryResults = contentIndex.search("important topic");
const tertiaryResults = tagIndex.search("important");

// Weight different result sources
const weightedResolver = new Resolver()
  .or(
    new Resolver(primaryResults).boost(3.0).resolve(),      // High weight for title matches
    new Resolver(secondaryResults).boost(1.5).resolve(),   // Medium weight for content matches
    new Resolver(tertiaryResults).boost(0.8).resolve()     // Lower weight for tag matches
  );

const rankedResults = weightedResolver
  .limit(25)
  .resolve({
    sortBy: "score",
    includeScores: true
  });

Configuration Options

ResolverOptions Interface

interface ResolverOptions {
  /** Initial search results to process */
  results?: IntermediateSearchResults;
  /** Default boost factor */
  defaultBoost?: number;
  /** Result processing mode */
  mode?: "intersection" | "union" | "difference";
  /** Custom scoring function */
  scorer?: (results: any[], query: string) => number[];
  /** Result deduplication strategy */
  dedupe?: boolean | "strict" | "loose";
}

ResolveOptions Interface

interface ResolveOptions {
  /** Include relevance scores in results */
  includeScores?: boolean;
  /** Result sorting strategy */
  sortBy?: "relevance" | "score" | "id" | "custom";
  /** Custom sorting function */
  customSort?: (a: any, b: any) => number;
  /** Result format configuration */
  format?: "simple" | "detailed" | "custom";
  /** Result post-processing function */
  postProcess?: (results: any[]) => any[];
  /** Include query metadata */
  includeMetadata?: boolean;
}

Advanced Configuration Examples

// Custom resolver with advanced options
const advancedResolver = new Resolver({
  defaultBoost: 1.2,
  mode: "intersection",
  dedupe: "strict",
  scorer: (results, query) => {
    // Custom scoring algorithm
    return results.map((result, index) => {
      const baseScore = 1.0;
      const positionPenalty = index * 0.1;
      const lengthBonus = Math.min(query.length / 10, 0.5);
      return baseScore - positionPenalty + lengthBonus;
    });
  }
});

// Resolution with detailed options
const detailedResults = advancedResolver.resolve({
  includeScores: true,
  sortBy: "custom",
  customSort: (a, b) => {
    // Custom sorting: primary by score, secondary by ID
    if (a.score !== b.score) {
      return b.score - a.score; // Descending by score
    }
    return a.id - b.id; // Ascending by ID
  },
  format: "detailed",
  postProcess: (results) => {
    // Add additional metadata to results
    return results.map(result => ({
      ...result,
      timestamp: Date.now(),
      searchVersion: "1.0"
    }));
  },
  includeMetadata: true
});

Types

type IntermediateSearchResults = Array<Id[]>;

interface ResolvedResult {
  id: Id;
  score?: number;
  metadata?: {
    query?: string;
    timestamp?: number;
    sources?: string[];
  };
}

interface DetailedResult extends ResolvedResult {
  boost: number;
  originalScore: number;
  finalScore: number;
  rank: number;
}

type BooleanOperation = "and" | "or" | "xor" | "not";
type SortingStrategy = "relevance" | "score" | "id" | "custom";
type ResultFormat = "simple" | "detailed" | "custom";