Skip to Content
ExamplesRAGUsageDatabase-Specific Configurations | RAG | Mastra Examples

Database-Specific Configurations

This example demonstrates how to use database-specific configurations with vector query tools to optimize performance and leverage unique features of different vector stores.

Multi-Environment Setup

Use different configurations for different environments:

import { openai } from "@ai-sdk/openai"; import { createVectorQueryTool } from "@mastra/rag"; import { RuntimeContext } from "@mastra/core/runtime-context"; // Base configuration const createSearchTool = (environment: 'dev' | 'staging' | 'prod') => { return createVectorQueryTool({ vectorStoreName: "pinecone", indexName: "documents", model: openai.embedding("text-embedding-3-small"), databaseConfig: { pinecone: { namespace: environment } } }); }; // Create environment-specific tools const devSearchTool = createSearchTool('dev'); const prodSearchTool = createSearchTool('prod'); // Or use runtime override const dynamicSearchTool = createVectorQueryTool({ vectorStoreName: "pinecone", indexName: "documents", model: openai.embedding("text-embedding-3-small") }); // Switch environment at runtime const switchEnvironment = async (environment: string, query: string) => { const runtimeContext = new RuntimeContext(); runtimeContext.set('databaseConfig', { pinecone: { namespace: environment } }); return await dynamicSearchTool.execute({ context: { queryText: query }, mastra, runtimeContext }); };

Performance Optimization with pgVector

Optimize search performance for different use cases:

// High accuracy configuration - slower but more precise const highAccuracyTool = createVectorQueryTool({ vectorStoreName: "postgres", indexName: "embeddings", model: openai.embedding("text-embedding-3-small"), databaseConfig: { pgvector: { ef: 400, // High accuracy for HNSW probes: 20, // High recall for IVFFlat minScore: 0.85 // High quality threshold } } }); // Use for critical searches where accuracy is paramount const criticalSearch = async (query: string) => { return await highAccuracyTool.execute({ context: { queryText: query, topK: 5 // Fewer, higher quality results }, mastra }); };

Multi-Tenant Application with Pinecone

Implement tenant isolation using Pinecone namespaces:

interface Tenant { id: string; name: string; namespace: string; } class MultiTenantSearchService { private searchTool: RagTool constructor() { this.searchTool = createVectorQueryTool({ vectorStoreName: "pinecone", indexName: "shared-documents", model: openai.embedding("text-embedding-3-small") }); } async searchForTenant(tenant: Tenant, query: string) { const runtimeContext = new RuntimeContext(); // Isolate search to tenant's namespace runtimeContext.set('databaseConfig', { pinecone: { namespace: tenant.namespace } }); const results = await this.searchTool.execute({ context: { queryText: query, topK: 10 }, mastra, runtimeContext }); // Add tenant context to results return { tenant: tenant.name, query, results: results.relevantContext, sources: results.sources }; } async bulkSearchForTenants(tenants: Tenant[], query: string) { const promises = tenants.map(tenant => this.searchForTenant(tenant, query) ); return await Promise.all(promises); } } // Usage const searchService = new MultiTenantSearchService(); const tenants = [ { id: '1', name: 'Company A', namespace: 'company-a' }, { id: '2', name: 'Company B', namespace: 'company-b' } ]; const results = await searchService.searchForTenant( tenants[0], "product documentation" );

Hybrid Search with Pinecone

Combine semantic and keyword search:

const hybridSearchTool = createVectorQueryTool({ vectorStoreName: "pinecone", indexName: "documents", model: openai.embedding("text-embedding-3-small"), databaseConfig: { pinecone: { namespace: "production", sparseVector: { // Example sparse vector for keyword "API" indices: [1, 5, 10, 15], values: [0.8, 0.6, 0.4, 0.2] } } } }); // Helper function to generate sparse vectors for keywords const generateSparseVector = (keywords: string[]) => { // This is a simplified example - in practice, you'd use // a proper sparse encoding method like BM25 const indices: number[] = []; const values: number[] = []; keywords.forEach((keyword, i) => { const hash = keyword.split('').reduce((a, b) => { a = ((a << 5) - a) + b.charCodeAt(0); return a & a; }, 0); indices.push(Math.abs(hash) % 1000); values.push(1.0 / (i + 1)); // Decrease weight for later keywords }); return { indices, values }; }; const hybridSearch = async (query: string, keywords: string[]) => { const runtimeContext = new RuntimeContext(); if (keywords.length > 0) { const sparseVector = generateSparseVector(keywords); runtimeContext.set('databaseConfig', { pinecone: { namespace: "production", sparseVector } }); } return await hybridSearchTool.execute({ context: { queryText: query }, mastra, runtimeContext }); }; // Usage const results = await hybridSearch( "How to use the REST API", ["API", "REST", "documentation"] );

Implement progressive search quality:

const createQualityGatedSearch = () => { const baseConfig = { vectorStoreName: "postgres", indexName: "embeddings", model: openai.embedding("text-embedding-3-small") }; return { // High quality search first highQuality: createVectorQueryTool({ ...baseConfig, databaseConfig: { pgvector: { minScore: 0.85, ef: 200, probes: 15 } } }), // Medium quality fallback mediumQuality: createVectorQueryTool({ ...baseConfig, databaseConfig: { pgvector: { minScore: 0.7, ef: 150, probes: 10 } } }), // Low quality last resort lowQuality: createVectorQueryTool({ ...baseConfig, databaseConfig: { pgvector: { minScore: 0.5, ef: 100, probes: 5 } } }) }; }; const progressiveSearch = async (query: string, minResults: number = 3) => { const tools = createQualityGatedSearch(); // Try high quality first let results = await tools.highQuality.execute({ context: { queryText: query }, mastra }); if (results.sources.length >= minResults) { return { quality: 'high', ...results }; } // Fallback to medium quality results = await tools.mediumQuality.execute({ context: { queryText: query }, mastra }); if (results.sources.length >= minResults) { return { quality: 'medium', ...results }; } // Last resort: low quality results = await tools.lowQuality.execute({ context: { queryText: query }, mastra }); return { quality: 'low', ...results }; }; // Usage const results = await progressiveSearch("complex technical query", 5); console.log(`Found ${results.sources.length} results with ${results.quality} quality`);

Key Takeaways

  1. Environment Isolation: Use namespaces to separate data by environment or tenant
  2. Performance Tuning: Adjust ef/probes parameters based on your accuracy vs speed requirements
  3. Quality Control: Use minScore to filter out low-quality matches
  4. Runtime Flexibility: Override configurations dynamically based on context
  5. Progressive Quality: Implement fallback strategies for different quality levels

This approach allows you to optimize vector search for your specific use case while maintaining flexibility and performance.