---
title: "Search Configuration"
source: "https://docs.vertesiahq.com/content/search"
markdown: "https://docs.vertesiahq.com/llms/content/search.md"
---

# Search Configuration

Vertesia's search backend is Elasticsearch, providing vector, full-text, and hybrid search from a single index. This guide covers how to configure and manage it.

## How search works

Documents are indexed in Elasticsearch automatically as they are created and updated, and a single index serves vector, full-text, and hybrid queries:

- **Vector similarity** — HNSW over document embeddings (`text`, `image`, and `properties`) for semantic search
- **Full-text** — stemming, fuzzy matching, and phrase queries
- **Hybrid** — vector and full-text combined, with configurable weights and score fusion (see [Hybrid Search](#hybrid-search))
- **Aggregations** — analytics, facets, and document statistics
- **DSL queries** — full control over search behavior for advanced cases

## Configuration

### Prerequisites

Elasticsearch requires:

1. Elasticsearch infrastructure enabled for your account
2. Embeddings configured (for vector search capabilities)
3. Project settings permission (`project:settings_write`)

### Enabling Elasticsearch

#### Get Status

Check the current Elasticsearch status for your project:

```bash {{title: 'cURL'}}
curl --location --request GET \
  'https://api.vertesia.io/api/v1/indexing/status' \
  --header 'Authorization: Bearer <YOUR_JWT_TOKEN>'
```

```typescript {{title: 'Vertesia SDK'}}
import { VertesiaClient } from '@vertesia/client';

const client = new VertesiaClient({
  serverUrl: 'https://api.vertesia.io',
  apikey: '<YOUR_API_KEY>',
});

const status = await client.store.indexing.status();
console.log(status);
```

**Example Response:**

```json
{
  "infrastructure_enabled": true,
  "indexing_enabled": true,
  "query_enabled": true,
  "index": {
    "exists": true,
    "alias_name": "content_abc123",
    "index_name": "content_abc123_v1",
    "version": 1,
    "created_at": "2024-01-15T10:00:00Z",
    "document_count": 15234,
    "size_bytes": 52428800
  },
  "mongo_document_count": 15234,
  "reindex_in_progress": false,
  "reindex_progress": null
}
```

#### Enable Indexing

Enable Elasticsearch indexing for your project. This creates the index and starts syncing documents:

```bash {{title: 'cURL'}}
curl --location --request POST \
  'https://api.vertesia.io/api/v1/indexing/enable-indexing' \
  --header 'Authorization: Bearer <YOUR_JWT_TOKEN>'
```

```typescript {{title: 'Vertesia SDK'}}
import { VertesiaClient } from '@vertesia/client';

const client = new VertesiaClient({
  serverUrl: 'https://api.vertesia.io',
  apikey: '<YOUR_API_KEY>',
});

const response = await client.store.indexing.enableIndexing();
console.log(response);
```

#### Enable Queries

Queries are now automatically enabled when indexing is enabled. This endpoint is kept for backward compatibility.

```bash {{title: 'cURL'}}
curl --location --request POST \
  'https://api.vertesia.io/api/v1/indexing/enable-queries' \
  --header 'Authorization: Bearer <YOUR_JWT_TOKEN>'
```

```typescript {{title: 'Vertesia SDK'}}
import { VertesiaClient } from '@vertesia/client';

const client = new VertesiaClient({
  serverUrl: 'https://api.vertesia.io',
  apikey: '<YOUR_API_KEY>',
});

const response = await client.store.indexing.enableQueries();
console.log(response);
```

#### Disable Queries

Queries are now automatically enabled when indexing is enabled. To disable queries, disable indexing instead.

```bash {{title: 'cURL'}}
curl --location --request POST \
  'https://api.vertesia.io/api/v1/indexing/disable-queries' \
  --header 'Authorization: Bearer <YOUR_JWT_TOKEN>'
```

```typescript {{title: 'Vertesia SDK'}}
import { VertesiaClient } from '@vertesia/client';

const client = new VertesiaClient({
  serverUrl: 'https://api.vertesia.io',
  apikey: '<YOUR_API_KEY>',
});

const response = await client.store.indexing.disableQueries();
console.log(response);
```

#### Disable Indexing

Disable Elasticsearch indexing entirely:

```bash {{title: 'cURL'}}
curl --location --request POST \
  'https://api.vertesia.io/api/v1/indexing/disable-indexing' \
  --header 'Authorization: Bearer <YOUR_JWT_TOKEN>'
```

```typescript {{title: 'Vertesia SDK'}}
import { VertesiaClient } from '@vertesia/client';

const client = new VertesiaClient({
  serverUrl: 'https://api.vertesia.io',
  apikey: '<YOUR_API_KEY>',
});

const response = await client.store.indexing.disableIndexing();
console.log(response);
```

### Reindexing

Reindexing rebuilds the Elasticsearch index from MongoDB. This may be needed when:

- Enabling Elasticsearch for an existing project with documents
- Changing embedding dimensions
- Index corruption or sync issues
- Recovering from failures

#### Trigger Reindex

```bash {{title: 'cURL'}}
curl --location --request POST \
  'https://api.vertesia.io/api/v1/indexing/reindex' \
  --header 'Authorization: Bearer <YOUR_JWT_TOKEN>' \
  --header 'Content-Type: application/json' \
  --data-raw '{
    "recreate_index": false
  }'
```

```typescript {{title: 'Vertesia SDK'}}
import { VertesiaClient } from '@vertesia/client';

const client = new VertesiaClient({
  serverUrl: 'https://api.vertesia.io',
  apikey: '<YOUR_API_KEY>',
});

const response = await client.store.indexing.reindex(false);
console.log(response);
```

**Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `recreate_index` | boolean | If `true`, drops and recreates the index. Use when changing dimensions or mappings. |

#### Zero-Downtime Reindexing

Vertesia uses alias-based reindexing for zero downtime:

1. A new index is created with updated mappings
2. Documents are batch-indexed to the new index
3. The alias is atomically swapped from old to new
4. The old index is deleted

During reindexing, queries continue to work against the existing index.

#### Monitoring Progress

Check reindex progress through the status endpoint:

```json
{
  "reindex_progress": {
    "status": "running",
    "processed": 5000,
    "total": 15234,
    "current_batch": 10,
    "total_batches": 31,
    "percent_complete": 33
  }
}
```

### Drift Analysis

Use drift analysis to measure how Elasticsearch has diverged from MongoDB without rebuilding the index. The analyzer compares documents by `_id` and `updated_at`.

#### Start Drift Analysis

```bash {{title: 'cURL'}}
curl --location --request POST \
  'https://api.vertesia.io/api/v1/indexing/analyze-drift' \
  --header 'Authorization: Bearer <YOUR_JWT_TOKEN>'
```

```typescript {{title: 'Vertesia SDK'}}
import { VertesiaClient } from '@vertesia/client';

const client = new VertesiaClient({
  serverUrl: 'https://api.vertesia.io',
  apikey: '<YOUR_API_KEY>',
});

const response = await client.store.indexing.analyzeDrift();
console.log(response);
```

#### Check Drift Analysis Status

```bash {{title: 'cURL'}}
curl --location --request GET \
  'https://api.vertesia.io/api/v1/indexing/drift-analysis' \
  --header 'Authorization: Bearer <YOUR_JWT_TOKEN>'
```

```typescript {{title: 'Vertesia SDK'}}
import { VertesiaClient } from '@vertesia/client';

const client = new VertesiaClient({
  serverUrl: 'https://api.vertesia.io',
  apikey: '<YOUR_API_KEY>',
});

const status = await client.store.indexing.getDriftAnalysis();
console.log(status);
```

**Example Completed Response:**

```json
{
  "workflow_id": "analyzeElasticsearchDriftWorkflow:project-abc123",
  "workflow_run_id": "019d1edd-3ac9-7dbf-b78d-470c49771180",
  "status": "COMPLETED",
  "result": {
    "total": 15234,
    "processed": 15234,
    "missing": 8,
    "stale": 3,
    "sample_missing_ids": [
      "65f0c4d7a8f9e7a6e7d3b101"
    ],
    "sample_stale_ids": [
      "65f0c4d7a8f9e7a6e7d3b202"
    ],
    "completed_at": "2026-03-24T08:22:11.000Z"
  }
}
```

## Hybrid Search

Hybrid search combines full-text and vector search for optimal relevance. When both search types return results, scores are aggregated using configurable methods.

### Score Aggregation Methods

| Method | Algorithm | Best For |
|--------|-----------|----------|
| **RRF** | Reciprocal Rank Fusion | When relevance scores from different sources aren't directly comparable |
| **RSF** | Relevance Score Fusion | When you want to combine normalized scores directly |
| **Smart** | Automatic selection | General use, automatically picks the best method |

### Weight Configuration

Control the relative importance of each search type:

```json
{
  "query": {
    "full_text": "quarterly report",
    "vector": { "text": "financial analysis" },
    "weights": {
      "full_text": 2,
      "vector": 3
    }
  }
}
```

Higher weights give more influence to that search type. With the above configuration, vector search results are weighted 1.5x more than full-text results.

### Dynamic Scaling

When enabled, dynamic scaling adjusts weights automatically if one search type is unavailable:

```json
{
  "query": {
    "full_text": "quarterly report",
    "vector": { "text": "financial analysis" },
    "dynamic_scaling": "on"
  }
}
```

## Index Configuration Tools

Agents can query and update index configuration using built-in tools:

### get_index_configuration

Retrieves the current index status and configuration.

**Returns:**
- Index status (exists, healthy)
- Document count and size
- Embedding dimensions for each type
- Field mappings

### update_index_configuration

Updates index configuration with options to change embedding dimensions or trigger reindexing.

**Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `embedding_dimensions` | object | New dimensions for `text`, `image`, or `properties` |
| `force_reindex` | boolean | Trigger a full reindex |
| `user_confirmed` | boolean | Required confirmation (must use `ask_user` first) |

## Troubleshooting

### Documents Not Appearing in Search

1. Check that indexing is enabled (`indexing_enabled: true`)
2. Verify embeddings are configured and generating
3. Allow time for async indexing to complete
4. Check for sync issues in status endpoint

### Dimension Mismatch Errors

If you changed embedding dimensions:

1. Recalculate embeddings with new dimensions
2. Trigger reindex with `recreate_index: true`

### Search Returns No Results

1. Verify documents exist in MongoDB (`mongo_document_count`)
2. Check Elasticsearch document count matches
3. Test with broader queries or `match_all`
4. Verify query syntax is correct

### Reindex Stuck or Failed

1. Check workflow status in the Vertesia UI
2. Look for errors in workflow history
3. Ensure sufficient permissions
4. Try triggering a new reindex (will cancel stuck one)

## Best Practices

### Index Management

- Enable queries only after initial indexing completes
- Monitor document counts between MongoDB and Elasticsearch
- Schedule reindexing during low-traffic periods

### Search Configuration

- Start with `smart` score aggregation
- Tune weights based on search quality feedback
- Use facets for navigation and filtering
- Enable `analyze` for complex queries that benefit from LLM summarization

### Performance

- Use appropriate `limit` values (avoid fetching more than needed)
- Use `count_only` for pagination totals
- Stream large results to artifacts with `output_artifact`
- Consider DSL mode for complex aggregations

## Next Steps

- [Content Overview](/content/overview) - Understanding the full search architecture
- [Embeddings Configuration](/content/embeddings) - Configure embeddings for vector search
- [Built-in Tools](/agent-runner/tools) - Learn about search_documents and index tools
- [Commands API](/api/commands#indexing-elasticsearch) - Full API reference for indexing endpoints