# Upstash vector store The UpstashVector class provides vector search using [Upstash Vector](https://upstash.com/vector), a serverless vector database service that provides vector similarity search with metadata filtering capabilities and hybrid search support. ## Constructor options **url** (`string`): Upstash Vector database URL **token** (`string`): Upstash Vector API token ## Methods ### `createIndex()` Note: This method is a no-op for Upstash as indexes are created automatically. **indexName** (`string`): Name of the index to create **dimension** (`number`): Vector dimension (must match your embedding model) **metric** (`'cosine' | 'euclidean' | 'dotproduct'`): Distance metric for similarity search (Default: `cosine`) ### `upsert()` **indexName** (`string`): Name of the index to upsert into **vectors** (`number[][]`): Array of embedding vectors **sparseVectors** (`{ indices: number[], values: number[] }[]`): Array of sparse vectors for hybrid search. Each sparse vector must have matching indices and values arrays. **metadata** (`Record[]`): Metadata for each vector **ids** (`string[]`): Optional vector IDs (auto-generated if not provided) ### `query()` **indexName** (`string`): Name of the index to query **queryVector** (`number[]`): Query vector to find similar vectors **sparseVector** (`{ indices: number[], values: number[] }`): Optional sparse vector for hybrid search. Must have matching indices and values arrays. **topK** (`number`): Number of results to return (Default: `10`) **filter** (`Record`): Metadata filters for the query **includeVector** (`boolean`): Whether to include vectors in the results (Default: `false`) **fusionAlgorithm** (`FusionAlgorithm`): Algorithm used to combine dense and sparse search results in hybrid search (e.g., RRF - Reciprocal Rank Fusion) **queryMode** (`QueryMode`): Search mode: 'DENSE' for dense-only, 'SPARSE' for sparse-only, or 'HYBRID' for combined search ### `listIndexes()` Returns an array of index names (namespaces) as strings. ### `describeIndex()` **indexName** (`string`): Name of the index to describe Returns: ```typescript interface IndexStats { dimension: number count: number metric: 'cosine' | 'euclidean' | 'dotproduct' } ``` ### `deleteIndex()` **indexName** (`string`): Name of the index (namespace) to delete ### `updateVector()` **indexName** (`string`): Name of the index to update **id** (`string`): ID of the item to update **update** (`object`): Update object containing vector, sparse vector, and/or metadata The `update` object can have the following properties: - `vector` (optional): An array of numbers representing the new dense vector. - `sparseVector` (optional): A sparse vector object with `indices` and `values` arrays for hybrid indexes. - `metadata` (optional): A record of key-value pairs for metadata. ### `deleteVector()` **indexName** (`string`): Name of the index from which to delete the item **id** (`string`): ID of the item to delete Attempts to delete an item by its ID from the specified index. Logs an error message if the deletion fails. ## Hybrid vector search Upstash Vector supports hybrid search that combines semantic search (dense vectors) with keyword-based search (sparse vectors) for improved relevance and accuracy. ### Basic Hybrid Usage ```typescript import { UpstashVector } from '@mastra/upstash' const vectorStore = new UpstashVector({ id: 'upstash-vector', url: process.env.UPSTASH_VECTOR_URL, token: process.env.UPSTASH_VECTOR_TOKEN, }) // Upsert vectors with both dense and sparse components const denseVectors = [ [0.1, 0.2, 0.3], [0.4, 0.5, 0.6], ] const sparseVectors = [ { indices: [1, 5, 10], values: [0.8, 0.6, 0.4] }, { indices: [2, 6, 11], values: [0.7, 0.5, 0.3] }, ] await vectorStore.upsert({ indexName: 'hybrid-index', vectors: denseVectors, sparseVectors: sparseVectors, metadata: [{ title: 'Document 1' }, { title: 'Document 2' }], }) // Query with hybrid search const results = await vectorStore.query({ indexName: 'hybrid-index', queryVector: [0.1, 0.2, 0.3], sparseVector: { indices: [1, 5], values: [0.9, 0.7] }, topK: 10, }) ``` ### Advanced Hybrid Search Options ```typescript import { FusionAlgorithm, QueryMode } from '@upstash/vector' // Query with specific fusion algorithm const fusionResults = await vectorStore.query({ indexName: 'hybrid-index', queryVector: [0.1, 0.2, 0.3], sparseVector: { indices: [1, 5], values: [0.9, 0.7] }, fusionAlgorithm: FusionAlgorithm.RRF, topK: 10, }) // Dense-only search const denseResults = await vectorStore.query({ indexName: 'hybrid-index', queryVector: [0.1, 0.2, 0.3], queryMode: QueryMode.DENSE, topK: 10, }) // Sparse-only search const sparseResults = await vectorStore.query({ indexName: 'hybrid-index', queryVector: [0.1, 0.2, 0.3], // Still required for index structure sparseVector: { indices: [1, 5], values: [0.9, 0.7] }, queryMode: QueryMode.SPARSE, topK: 10, }) ``` ### Updating Hybrid Vectors ```typescript // Update both dense and sparse components await vectorStore.updateVector({ indexName: 'hybrid-index', id: 'vector-id', update: { vector: [0.2, 0.3, 0.4], sparseVector: { indices: [2, 7, 12], values: [0.9, 0.8, 0.6] }, metadata: { title: 'Updated Document' }, }, }) ``` ## Response types Query results are returned in this format: ```typescript interface QueryResult { id: string score: number metadata: Record vector?: number[] // Only included if includeVector is true } ``` ## Error handling The store throws typed errors that can be caught: ```typescript try { await store.query({ indexName: 'index_name', queryVector: queryVector, }) } catch (error) { if (error instanceof VectorStoreError) { console.log(error.code) // 'connection_failed' | 'invalid_dimension' | etc console.log(error.details) // Additional error context } } ``` ## Environment variables Required environment variables: - `UPSTASH_VECTOR_URL`: Your Upstash Vector database URL - `UPSTASH_VECTOR_TOKEN`: Your Upstash Vector API token ## Usage example ### Local embeddings with fastembed Embeddings are numeric vectors used by memory's `semanticRecall` to retrieve related messages by meaning (not keywords). This setup uses `@mastra/fastembed` to generate vector embeddings. Install `fastembed` to get started: **npm**: ```bash npm install @mastra/fastembed@latest ``` **pnpm**: ```bash pnpm add @mastra/fastembed@latest ``` **Yarn**: ```bash yarn add @mastra/fastembed@latest ``` **Bun**: ```bash bun add @mastra/fastembed@latest ``` Add the following to your agent: ```typescript import { Memory } from '@mastra/memory' import { Agent } from '@mastra/core/agent' import { UpstashStore, UpstashVector } from '@mastra/upstash' import { fastembed } from '@mastra/fastembed' export const upstashAgent = new Agent({ id: 'upstash-agent', name: 'Upstash Agent', instructions: 'You are an AI agent with the ability to automatically recall memories from previous interactions.', model: 'openai/gpt-5.4', memory: new Memory({ storage: new UpstashStore({ id: 'upstash-agent-storage', url: process.env.UPSTASH_REDIS_REST_URL!, token: process.env.UPSTASH_REDIS_REST_TOKEN!, }), vector: new UpstashVector({ id: 'upstash-agent-vector', url: process.env.UPSTASH_VECTOR_REST_URL!, token: process.env.UPSTASH_VECTOR_REST_TOKEN!, }), embedder: fastembed, options: { lastMessages: 10, semanticRecall: { topK: 3, messageRange: 2, }, }, }), }) ``` ## Related - [Metadata Filters](https://mastra.ai/reference/rag/metadata-filters)