stores/upstash/README.md
Upstash provider for Mastra that includes both vector store and database storage capabilities.
npm install @mastra/upstash
import { UpstashVector } from '@mastra/upstash';
// In upstash they refer to the store as an index
const vectorStore = new UpstashVector({
url: process.env.UPSTASH_VECTOR_REST_URL,
token: process.env.UPSTASH_VECTOR_TOKEN
});
// Add vectors
const vectors = [[0.1, 0.2, ...], [0.3, 0.4, ...]];
const metadata = [{ text: 'doc1' }, { text: 'doc2' }];
const ids = await vectorStore.upsert({
indexName: 'my-namespace',
vectors,
metadata
});
// There is no store.createIndex call here, Upstash creates indexes (known as namespaces in Upstash) automatically
// when you upsert if that namespace does not exist yet.
// Query vectors
const results = await vectorStore.query({
indexName: 'my-namespace',
queryVector: [0.1, 0.2, ...],
topK: 10,
filter: { text: { $eq: 'doc1' } },
includeVector: false
});
Upstash supports hybrid search that combines semantic search (dense vectors) with keyword-based search (sparse vectors) for improved relevance and accuracy.
import { UpstashVector } from '@mastra/upstash';
const vectorStore = new UpstashVector({
url: process.env.UPSTASH_VECTOR_REST_URL,
token: process.env.UPSTASH_VECTOR_TOKEN
});
const vectors = [[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] }
];
const metadata = [{ title: 'Document 1' }, { title: 'Document 2' }];
const ids = await vectorStore.upsert({
indexName: 'hybrid-index',
vectors,
sparseVectors,
metadata
});
import { FusionAlgorithm, QueryMode } from '@upstash/vector';
// Query with both dense and sparse vectors (default hybrid mode)
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,
fusionAlgorithm: FusionAlgorithm.RRF,
includeVector: false
});
// Dense-only query (backward compatible)
const denseResults = await vectorStore.query({
indexName: 'hybrid-index',
queryVector: [0.1, 0.2, 0.3, ...],
topK: 10
});
// Query only the dense component for custom reranking
const denseOnlyResults = await vectorStore.query({
indexName: 'hybrid-index',
queryVector: [0.1, 0.2, 0.3, ...],
queryMode: QueryMode.DENSE,
topK: 10
});
// Query only the sparse component for custom reranking
const sparseOnlyResults = await vectorStore.query({
indexName: 'hybrid-index',
queryVector: [0.1, 0.2, 0.3, ...], // Still needed for dense index structure
sparseVector: { indices: [1, 5], values: [0.9, 0.7] },
queryMode: QueryMode.SPARSE,
topK: 10
});
// Explicit hybrid mode (same as default)
const explicitHybridResults = await vectorStore.query({
indexName: 'hybrid-index',
queryVector: [0.1, 0.2, 0.3, ...],
sparseVector: { indices: [1, 5], values: [0.9, 0.7] },
queryMode: QueryMode.HYBRID,
fusionAlgorithm: FusionAlgorithm.RRF,
topK: 10
});
Upstash provides built-in fusion algorithms to combine dense and sparse search results:
Query modes enable fine-grained control over hybrid index queries:
QueryMode.HYBRID: Default mode that queries both dense and sparse components and fuses resultsQueryMode.DENSE: Query only the dense component, useful for custom reranking scenariosQueryMode.SPARSE: Query only the sparse component, useful for custom reranking scenariosUse query modes when you want to implement custom fusion logic or need separate dense/sparse results for advanced reranking algorithms.
The Upstash vector store requires the following configuration:
UPSTASH_VECTOR_REST_URL: Your Upstash Vector REST URLUPSTASH_VECTOR_TOKEN: Your Upstash Vector REST tokenUPSTASH_INDEX: Name of the index to useimport { UpstashStore } from '@mastra/upstash';
const store = new UpstashStore({
url: process.env.UPSTASH_REDIS_REST_URL,
token: process.env.UPSTASH_REDIS_REST_TOKEN,
});
The Upstash store requires the following configuration:
UPSTASH_REDIS_REST_URL: Your Upstash Redis REST URLUPSTASH_REDIS_REST_TOKEN: Your Upstash Redis REST tokencreateIndex({ indexName, dimension, metric? }): Create a new namespaceupsert({ indexName, vectors, sparseVectors?, metadata?, ids? }): Add or update vectors (supports hybrid search)query({ indexName, queryVector, sparseQueryVector?, topK?, filter?, includeVector?, includeMetadata?, mode?, fusionAlgorithm? }): Search for similar vectorsupdateVector({ indexName, id?, filter?, update }): Update a single vector by ID or metadata filterdeleteVector({ indexName, id }): Delete a single vector by IDdeleteVectors({ indexName, ids?, filter? }): Delete multiple vectors by IDs or metadata filterlistIndexes(): List all namespacesdescribeIndex({ indexName }): Get namespace statisticsdeleteIndex({ indexName }): Delete a namespace