or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

administration.mdaql-queries.mddatabase-connection.mddocument-collections.mdgraph-operations.mdindex.mdquery-execution.mdtransactions.mdviews-search.md
tile.json

views-search.mddocs/

Views and Search

ArangoSearch views and full-text search capabilities for advanced querying, indexing, and real-time search functionality across collections.

Capabilities

View Management

Create and manage ArangoSearch views and SearchAlias views for advanced search capabilities.

/**
 * Gets a reference to a view
 * @param viewName - Name of the view
 * @returns View instance
 */
view(viewName: string): View;

/**
 * Creates a new view (ArangoSearch or SearchAlias)
 * @param viewName - Name for the new view
 * @param options - View creation options
 * @returns Promise resolving to View instance
 */
createView(viewName: string, options: CreateViewOptions): Promise<View>;

/**
 * Lists all views in the database
 * @returns Promise resolving to array of View instances
 */
views(): Promise<View[]>;

Usage Examples:

import { Database } from "arangojs";

const db = new Database();

// Create ArangoSearch view for full-text search
const searchView = await db.createView("article_search", {
  type: "arangosearch",
  links: {
    articles: {
      analyzers: ["text_en", "identity"],
      fields: {
        title: { analyzers: ["text_en"] },
        content: { analyzers: ["text_en"] },
        tags: { analyzers: ["identity"] },
        author: { 
          fields: {
            name: { analyzers: ["text_en"] }
          }
        }
      },
      includeAllFields: false,
      storeValues: "none",
      trackListPositions: false
    },
    comments: {
      analyzers: ["text_en"],
      fields: {
        text: { analyzers: ["text_en"] },
        author: { analyzers: ["identity"] }
      }
    }
  },
  primarySort: [
    { field: "createdAt", direction: "desc" }
  ],
  storedValues: [
    { fields: ["title", "author.name"], compression: "lz4" }
  ]
});

// Create SearchAlias view (Enterprise Edition)
const aliasView = await db.createView("content_search", {
  type: "search-alias",
  indexes: [
    { collection: "articles", index: "article_text_index" },
    { collection: "blogs", index: "blog_search_index" }
  ]
});

// Get reference to existing view
const existingView = db.view("article_search");

// List all views
const allViews = await db.views();
console.log(`Found ${allViews.length} views in database`);

View Information and Configuration

Retrieve and manage view metadata and configuration.

/**
 * View class for managing ArangoSearch and SearchAlias views
 */
class View {
  /** View name */
  readonly name: string;

  /**
   * Checks if the view exists
   * @returns Promise resolving to boolean indicating existence
   */
  exists(): Promise<boolean>;

  /**
   * Retrieves view information and metadata
   * @returns Promise resolving to view description
   */
  get(): Promise<ViewDescription>;

  /**
   * Creates the view with specified options
   * @param options - View creation options
   * @returns Promise resolving to view description
   */
  create(options: CreateViewOptions): Promise<ViewDescription>;

  /**
   * Gets or sets view properties
   * @param properties - Properties to update (optional)
   * @returns Promise resolving to current/updated properties
   */
  properties(properties?: ViewPropertiesOptions): Promise<ViewProperties>;

  /**
   * Updates view properties (partial update)
   * @param properties - Properties to update
   * @returns Promise resolving to updated properties
   */
  updateProperties(properties: ViewPropertiesOptions): Promise<ViewProperties>;

  /**
   * Replaces all view properties
   * @param properties - New properties to set
   * @returns Promise resolving to new properties
   */
  replaceProperties(properties: ViewPropertiesOptions): Promise<ViewProperties>;

  /**
   * Renames the view
   * @param newName - New name for the view
   * @returns Promise resolving to updated view description
   */
  rename(newName: string): Promise<ViewDescription>;

  /**
   * Drops (deletes) the view
   * @returns Promise resolving when view is dropped
   */
  drop(): Promise<void>;
}

Usage Examples:

const view = db.view("article_search");

// Check if view exists
if (!(await view.exists())) {
  await view.create({
    type: "arangosearch",
    links: {
      articles: {
        analyzers: ["text_en"],
        fields: { title: {}, content: {} }
      }
    }
  });
}

// Get view information
const info = await view.get();
console.log("View type:", info.type);
console.log("Collections linked:", Object.keys(info.links || {}));

// Update view properties to add new collection
await view.updateProperties({
  links: {
    ...info.links,
    news: {
      analyzers: ["text_en"],
      fields: {
        headline: { analyzers: ["text_en"] },
        body: { analyzers: ["text_en"] }
      }
    }
  }
});

// Get updated properties
const updatedProps = await view.properties();
console.log("Updated view links:", Object.keys(updatedProps.links || {}));

// Rename view
await view.rename("content_search_v2");

// Eventually drop view
await view.drop();

Search Query Operations

Execute search queries using ArangoSearch views with advanced search features.

Usage Examples:

// Full-text search with ArangoSearch view
const searchResults = await db.query(aql`
  FOR doc IN article_search
  SEARCH ANALYZER(
    PHRASE(doc.title, "machine learning") OR 
    PHRASE(doc.content, "artificial intelligence"),
    "text_en"
  )
  SORT TFIDF(doc) DESC
  LIMIT 10
  RETURN {
    title: doc.title,
    author: doc.author.name,
    snippet: LEFT(doc.content, 200),
    score: TFIDF(doc)
  }
`);

// Advanced search with multiple criteria
const advancedSearch = await db.query(aql`
  FOR doc IN article_search
  SEARCH (
    ANALYZER(PHRASE(doc.title, ${searchTerm}), "text_en") OR
    ANALYZER(PHRASE(doc.content, ${searchTerm}), "text_en")
  )
  AND doc.tags ANY IN ${allowedTags}
  AND doc.publishedAt >= ${startDate}
  
  // Boost recent articles
  LET boost = doc.publishedAt > DATE_SUBTRACT(DATE_NOW(), 30, "day") ? 2 : 1
  
  SORT TFIDF(doc) * boost DESC, doc.publishedAt DESC
  LIMIT ${offset}, ${limit}
  
  RETURN {
    id: doc._key,
    title: doc.title,
    author: doc.author.name, 
    publishedAt: doc.publishedAt,
    tags: doc.tags,
    relevanceScore: TFIDF(doc) * boost,
    // Use stored values for performance
    storedTitle: doc.title,
    storedAuthor: doc.author.name
  }
`);

// Faceted search with aggregations
const facetedSearch = await db.query(aql`
  FOR doc IN article_search
  SEARCH ANALYZER(PHRASE(doc.content, ${query}), "text_en")
  
  COLLECT 
    category = doc.category,
    author = doc.author.name
  AGGREGATE count = LENGTH()
  
  RETURN {
    category,
    author,
    count
  }
`);

// Geospatial search combined with text search
const geoTextSearch = await db.query(aql`
  FOR doc IN venue_search
  SEARCH (
    ANALYZER(PHRASE(doc.name, ${venueName}), "text_en") OR
    ANALYZER(PHRASE(doc.description, ${searchText}), "text_en")
  )
  AND GEO_DISTANCE(doc.location, ${userLocation}) <= ${radiusKm} * 1000
  
  SORT GEO_DISTANCE(doc.location, ${userLocation}) ASC
  LIMIT 20
  
  RETURN {
    name: doc.name,
    description: doc.description,
    location: doc.location,
    distance: GEO_DISTANCE(doc.location, ${userLocation})
  }
`);

Advanced Search Features

Advanced search capabilities including custom scoring, highlighting, and real-time indexing.

Usage Examples:

// Custom scoring with multiple factors
const customScoredSearch = await db.query(aql`
  FOR doc IN article_search
  SEARCH ANALYZER(PHRASE(doc.content, ${searchTerm}), "text_en")
  
  // Custom relevance scoring
  LET textScore = TFIDF(doc)
  LET recencyScore = (DATE_NOW() - doc.publishedAt) / (1000 * 60 * 60 * 24 * 30) // Age in months
  LET popularityScore = LOG10(doc.viewCount + 1)
  LET authorScore = doc.author.reputation / 100
  
  LET finalScore = textScore * 0.4 + 
                   (1 / (recencyScore + 1)) * 0.2 + 
                   popularityScore * 0.3 + 
                   authorScore * 0.1
  
  SORT finalScore DESC
  LIMIT 20
  
  RETURN {
    title: doc.title,
    author: doc.author.name,
    publishedAt: doc.publishedAt,
    viewCount: doc.viewCount,
    scores: {
      text: textScore,
      recency: recencyScore,
      popularity: popularityScore,
      author: authorScore,
      final: finalScore
    }
  }
`);

// Search with highlighting (requires stored values or re-fetch)
const highlightedSearch = await db.query(aql`
  FOR doc IN article_search
  SEARCH ANALYZER(PHRASE(doc.content, ${searchTerm}), "text_en")
  SORT TFIDF(doc) DESC
  LIMIT 10
  
  // Get full document for highlighting
  LET fullDoc = DOCUMENT("articles", doc._key)
  
  RETURN {
    id: doc._key,
    title: fullDoc.title,
    content: fullDoc.content,
    score: TFIDF(doc),
    // Client-side highlighting needed for content
    searchTerm: ${searchTerm}
  }
`);

// Real-time search with filters
const realtimeSearch = await db.query(aql`
  FOR doc IN live_content_search
  SEARCH (
    ANALYZER(PHRASE(doc.title, ${query}) OR PHRASE(doc.content, ${query}), "text_en")
  )
  AND doc.status == "published"
  AND doc.publishedAt >= ${Date.now() - 24 * 60 * 60 * 1000} // Last 24 hours
  
  // Use primary sort from view definition
  SORT doc.publishedAt DESC
  LIMIT 50
  
  RETURN {
    id: doc._key,
    title: doc.title,
    publishedAt: doc.publishedAt,
    author: doc.author,
    summary: LEFT(doc.content, 300)
  }
`);

// Multi-language search
const multilingualSearch = await db.query(aql`
  FOR doc IN multilingual_search
  SEARCH (
    ANALYZER(PHRASE(doc.title_en, ${englishQuery}), "text_en") OR
    ANALYZER(PHRASE(doc.title_es, ${spanishQuery}), "text_es") OR
    ANALYZER(PHRASE(doc.title_fr, ${frenchQuery}), "text_fr")
  )
  
  SORT TFIDF(doc) DESC
  LIMIT 20
  
  RETURN {
    id: doc._key,
    titles: {
      en: doc.title_en,
      es: doc.title_es, 
      fr: doc.title_fr
    },
    language: doc.primary_language,
    score: TFIDF(doc)
  }
`);

View Optimization and Maintenance

Optimize view performance and manage index maintenance.

/**
 * Gets view optimization statistics
 * @returns Promise resolving to optimization stats
 */
getOptimizationStats(): Promise<ViewOptimizationStats>;

/**
 * Triggers view optimization/consolidation
 * @param options - Optimization options
 * @returns Promise resolving when optimization starts
 */
optimize(options?: ViewOptimizationOptions): Promise<void>;

/**
 * Gets view indexing progress and statistics
 * @returns Promise resolving to indexing stats
 */
getIndexingStats(): Promise<ViewIndexingStats>;

Usage Examples:

const view = db.view("large_content_search");

// Check optimization stats
const optimizationStats = await view.getOptimizationStats();
console.log("Segments count:", optimizationStats.segmentsCount);
console.log("Memory usage:", optimizationStats.memoryUsage);
console.log("Last optimization:", optimizationStats.lastOptimization);

if (optimizationStats.segmentsCount > 10) {
  // Trigger optimization
  await view.optimize({
    maxSegments: 5,
    waitForCompletion: false
  });
  console.log("View optimization started");
}

// Monitor indexing progress
const indexingStats = await view.getIndexingStats();
console.log("Documents indexed:", indexingStats.documentsIndexed);
console.log("Indexing progress:", `${indexingStats.progress * 100}%`);
console.log("Index size:", indexingStats.indexSize);

// Performance monitoring query
const performanceMetrics = await db.query(aql`
  FOR doc IN article_search
  SEARCH ANALYZER(PHRASE(doc.content, "test query"), "text_en")
  OPTIONS { profile: true }
  LIMIT 1
  RETURN doc
`);

console.log("Query execution time:", performanceMetrics.extra.profile.executing);

Types

class View {
  readonly name: string;
  exists(): Promise<boolean>;
  get(): Promise<ViewDescription>;
  create(options: CreateViewOptions): Promise<ViewDescription>;
  properties(properties?: ViewPropertiesOptions): Promise<ViewProperties>;
  updateProperties(properties: ViewPropertiesOptions): Promise<ViewProperties>;
  replaceProperties(properties: ViewPropertiesOptions): Promise<ViewProperties>;
  rename(newName: string): Promise<ViewDescription>;
  drop(): Promise<void>;
}

type CreateViewOptions = ArangoSearchViewOptions | SearchAliasViewOptions;

interface ArangoSearchViewOptions {
  type: "arangosearch";
  links?: Record<string, ArangoSearchViewLinkOptions>;
  primarySort?: ArangoSearchViewPrimarySortEntry[];
  storedValues?: ArangoSearchViewStoredValueOptions[];
  cleanupIntervalStep?: number;
  commitIntervalMsec?: number;
  consolidationIntervalMsec?: number;
  consolidationPolicy?: ArangoSearchViewConsolidationPolicy;
  writebufferIdle?: number;
  writebufferActive?: number;
  writebufferSizeMax?: number;
}

interface SearchAliasViewOptions {
  type: "search-alias";
  indexes: Array<{
    collection: string;
    index: string;
  }>;
}

interface ArangoSearchViewLinkOptions {
  analyzers?: string[];
  fields?: Record<string, ArangoSearchViewLinkOptions>;
  includeAllFields?: boolean;
  storeValues?: "none" | "id";
  trackListPositions?: boolean;
  cache?: boolean;
}

interface ArangoSearchViewPrimarySortEntry {
  field: string;
  direction?: Direction;
}

type Direction = "asc" | "desc";

interface ArangoSearchViewStoredValueOptions {
  fields: string[];
  compression?: Compression;
  cache?: boolean;
}

type Compression = "lz4" | "none";

interface ViewDescription {
  id: string;
  name: string;
  type: "arangosearch" | "search-alias";
  globallyUniqueId: string;
}

interface ArangoSearchViewDescription extends ViewDescription {
  type: "arangosearch";
  links: Record<string, ArangoSearchViewLinkOptions>;
  primarySort: ArangoSearchViewPrimarySortEntry[];
  storedValues: ArangoSearchViewStoredValueOptions[];
  cleanupIntervalStep: number;
  commitIntervalMsec: number;
  consolidationIntervalMsec: number;
  consolidationPolicy: ArangoSearchViewConsolidationPolicy;
  writebufferIdle: number;
  writebufferActive: number;
  writebufferSizeMax: number;
}

interface SearchAliasViewDescription extends ViewDescription {
  type: "search-alias";
  indexes: Array<{
    collection: string;
    index: string;
  }>;
}

type ViewProperties = ArangoSearchViewDescription | SearchAliasViewDescription;
type ViewPropertiesOptions = Partial<ArangoSearchViewOptions> | Partial<SearchAliasViewOptions>;

interface ArangoSearchViewConsolidationPolicy {
  type: "tier" | "bytes_accum";
  segmentsBytesFloor?: number;
  segmentsBytesMax?: number;
  segmentsMax?: number;
  segmentsMin?: number;
  minScore?: number;
}

interface ViewOptimizationStats {
  segmentsCount: number;
  memoryUsage: number;
  lastOptimization: string;
  optimizationInProgress: boolean;
}

interface ViewOptimizationOptions {
  maxSegments?: number;
  waitForCompletion?: boolean;
  timeout?: number;
}

interface ViewIndexingStats {
  documentsIndexed: number;
  totalDocuments: number;
  progress: number;
  indexSize: number;
  lastUpdate: string;
  isUpToDate: boolean;
}