RemoteVectorDB Client
The RemoteVectorDB client provides a powerful HTTP interface to LocalVectorDB servers with near-perfect API parity to the local LocalVectorDB implementation. This enables a seamless development-to-production workflow: rapidly prototype with LocalVectorDB locally, then deploy to production using RemoteVectorDB without changing your code.
Overview
RemoteVectorDB is the HTTP client for LocalVectorDB that maintains complete API compatibility with the local implementation. This design philosophy enables developers to:
Develop Locally: Start with
LocalVectorDBfor rapid prototyping with no server setupTest Remotely: Switch to
RemoteVectorDBfor integration testingDeploy to Production: Use the same code in production with distributed servers
Scale Seamlessly: Add servers and load balancing without code changes
The client communicates with LocalVectorDB servers via a RESTful HTTP API, supporting:
Full document lifecycle management (CRUD operations)
Vector, keyword, and hybrid search
Metadata filtering and schema management
SQLite tuning and optimization
Async operations for high-performance applications
Automatic retry logic and connection pooling
Key Features
- Near-Perfect API Parity
Every method available in
LocalVectorDBis also available inRemoteVectorDB, including:All document operations (upsert, insert, get, update, delete)
All query methods (query, filter, query_multi_column)
Metadata schema management
Database tuning operations
Async variants of all methods
- Drop-in Replacement
Switch between local and remote with a single line change:
# Development: Local database db = LocalVectorDB("mydb", "./data") # Production: Remote database (same API!) db = RemoteVectorDB("mydb", "https://vectordb.company.com")
- VectorDB Factory Pattern
The
VectorDB()factory automatically selects the right implementation:from localvectordb import VectorDB # Automatically creates LocalVectorDB db = VectorDB("mydb", "./data") # Automatically creates RemoteVectorDB db = VectorDB("mydb", "https://vectordb.company.com")
- Built-in Resilience
Automatic retry with exponential backoff
Connection pooling for efficiency
Timeout configuration
Comprehensive error handling
- Authentication Support
API key authentication
Environment variable configuration
Custom authorization headers
Development Workflow
The LocalVectorDB ecosystem is designed for a natural progression from development to production:
1. Start with LocalVectorDB
Begin development using LocalVectorDB for immediate productivity:
from localvectordb import LocalVectorDB
from localvectordb.core import MetadataField, MetadataFieldType
# Local development database
db = LocalVectorDB(
name="products",
base_path="./dev_data",
metadata_schema={
'category': MetadataField(type=MetadataFieldType.TEXT, indexed=True),
'price': MetadataField(type=MetadataFieldType.REAL, indexed=True),
'in_stock': MetadataField(type=MetadataFieldType.BOOLEAN)
}
)
# Develop your application
db.upsert(documents, metadata=metadata)
results = db.query("search term", filters={"category": "electronics"})
2. Use VectorDB Factory for Flexibility
Refactor to use the VectorDB factory for environment-based configuration:
from localvectordb import VectorDB
import os
# Configuration from environment
db_path = os.getenv("VECTOR_DB_PATH", "./dev_data")
# Works with both local paths and URLs!
db = VectorDB(
name="products",
base_path=db_path, # "./dev_data" or "https://api.company.com"
api_key=os.getenv("LVDB_API_KEY"), # Ignored for local, used for remote
metadata_schema={
'category': MetadataField(type=MetadataFieldType.TEXT, indexed=True),
'price': MetadataField(type=MetadataFieldType.REAL, indexed=True),
'in_stock': MetadataField(type=MetadataFieldType.BOOLEAN)
}
)
3. Deploy with RemoteVectorDB
In production, simply change the configuration:
# Production: Set environment variables
# VECTOR_DB_PATH=https://vectordb.company.com
# LVDB_API_KEY=your-secure-api-key
# Same code works in production!
db = VectorDB(
name="products",
base_path=os.getenv("VECTOR_DB_PATH"),
api_key=os.getenv("LVDB_API_KEY")
)
Connection and Authentication
Basic Connection
Connect to a LocalVectorDB server:
from localvectordb.client import RemoteVectorDB
# Basic connection (no authentication)
db = RemoteVectorDB(
name="my_database",
base_url="http://localhost:8000"
)
# HTTPS connection with authentication
db = RemoteVectorDB(
name="my_database",
base_url="https://vectordb.company.com",
api_key="your-api-key"
)
Authentication Methods
RemoteVectorDB supports multiple authentication configurations:
Direct API Key:
db = RemoteVectorDB(
name="mydb",
base_url="https://api.example.com",
api_key="sk-abc123def456"
)
Environment Variable (default: LVDB_API_KEY):
# Automatically reads from LVDB_API_KEY
db = RemoteVectorDB(
name="mydb",
base_url="https://api.example.com"
)
Custom Environment Variable:
# Use a custom environment variable
db = RemoteVectorDB(
name="mydb",
base_url="https://api.example.com",
api_key="$MY_CUSTOM_API_KEY" # Reads from MY_CUSTOM_API_KEY env var
)
Connection Configuration
Fine-tune connection behavior:
from httpx import Limits
db = RemoteVectorDB(
name="mydb",
base_url="https://api.example.com",
api_key="your-api-key",
# Timeout configuration
request_timeout=30, # Request timeout in seconds
# Retry configuration
max_retries=3,
retry_delay=1.0, # Base delay for exponential backoff
# Connection pooling
connection_pool_limits=Limits(
max_keepalive_connections=20,
max_connections=100,
keepalive_expiry=30.0
),
# Concurrent request limits
max_concurrent_requests=5,
# Custom auth header (for non-standard servers)
authorization_header="X-API-Key"
)
Complete API Reference
RemoteVectorDB implements all methods from LocalVectorDB with both synchronous and asynchronous variants.
Document Operations
Upsert Documents:
# Sync: Add or update documents
doc_ids = db.upsert(
documents=["Document 1", "Document 2"],
metadata=[
{"author": "Alice", "year": 2024},
{"author": "Bob", "year": 2023}
],
ids=["doc1", "doc2"] # Optional custom IDs
)
# Async variant
doc_ids = await db.upsert_async(documents, metadata, ids)
Insert Documents:
# Sync: Insert new documents (fails if IDs exist)
doc_ids = db.insert(documents, metadata, ids)
# Async variant
doc_ids = await db.insert_async(documents, metadata, ids)
Get Documents:
# Get single document
doc = db.get("doc1")
# Get multiple documents
docs = db.get(["doc1", "doc2", "doc3"])
# Async variants
doc = await db.get_async("doc1")
docs = await db.get_async(["doc1", "doc2", "doc3"])
Update Documents:
# Update document content and/or metadata
db.update(
id="doc1",
content="Updated content", # Optional
metadata={"author": "Alice Smith", "updated": True} # Optional
)
# Async variant
await db.update_async(id, content, metadata)
Patch Documents (in-place edit):
# Edit a document without re-sending its whole content. Ops resolve against
# the current content (character offsets), touch disjoint spans, and apply
# atomically. Returns a PatchResult(updated, new_hash, ops_applied).
result = db.patch("doc1", [{"op": "replace", "find": "draft", "replace": "final"}])
# Span splice + append/prepend
db.patch("doc1", [{"op": "splice", "start": 0, "end": 5, "text": "Hello"}])
db.patch("doc1", [{"op": "append", "text": " (revised)"}])
# Optimistic concurrency: fail with PatchConflictError if the stored content
# changed since you read it. An unmatched/ambiguous find raises PatchError.
doc = db.get("doc1")
db.patch("doc1", [{"op": "replace", "find": "v1", "replace": "v2"}],
expect_hash=doc.content_hash)
# Async variant
result = await db.patch_async("doc1", [{"op": "append", "text": "!"}])
Note
patch is an interface win, not a compute win: it re-embeds the document
through the normal upsert path (unchanged chunks reuse their vectors). Its
value is that an agent need not regenerate — and risk corrupting — the whole
document to change one line, and can guard against lost updates with
expect_hash.
Delete Documents:
# Delete single or multiple documents
deleted_count = db.delete("doc1")
deleted_count = db.delete(["doc1", "doc2"])
# Async variants
deleted_count = await db.delete_async(ids)
Check Existence:
# Check if documents exist
exists = db.exists("doc1") # Returns: bool
exist_list = db.exists(["doc1", "doc2"]) # Returns: List[bool]
# Async variants
exists = await db.exists_async(ids)
Count Documents:
# Count all documents
total = db.count()
# Count with filters
count = db.count(filters={"author": "Alice", "year": {"$gte": 2023}})
# Async variant
count = await db.count_async(filters)
File Operations
Upsert from Files:
# Process files and add to database
doc_ids = db.upsert_from_file(
file_paths=["document.pdf", "report.docx"],
metadata=[
{"source": "research", "confidential": False},
{"source": "internal", "confidential": True}
],
ids=["pdf1", "docx1"], # Optional
# Optional security options passed through to the extractor
extractor_kwargs={"strip_dangerous_elements": True}
)
# Async variant
doc_ids = await db.upsert_from_file_async(
file_paths, metadata, ids
)
Insert from Files:
# Insert new files (fails if IDs exist)
doc_ids = db.insert_from_file(
file_paths, metadata, ids, errors="raise"
)
# Async variant
doc_ids = await db.insert_from_file_async(
file_paths, metadata, ids, errors="raise"
)
Chunk Operations
Upsert Chunks Directly:
from localvectordb.core import Chunk, ChunkPosition
# upsert_from_chunks takes a dict mapping each document ID to its chunks.
# Chunks may be plain strings or Chunk objects. A Chunk's fields are:
# content, position (a ChunkPosition), tokens, index, and the optional
# faiss_id / content_hash.
chunks_by_document = {
"doc1": [
Chunk(
content="First chunk content",
position=ChunkPosition(
start=0, end=100, line=1, column=1, end_line=5, end_column=20
),
tokens=18,
index=0,
),
Chunk(
content="Second chunk content",
position=ChunkPosition(
start=100, end=200, line=5, column=21, end_line=9, end_column=15
),
tokens=20,
index=1,
),
]
}
# Upsert chunks (per-document metadata is optional)
db.upsert_from_chunks(chunks_by_document, metadata={"doc1": {"section": "intro"}})
# A list of plain strings per document also works:
db.upsert_from_chunks({"doc2": ["chunk one text", "chunk two text"]})
# Async variant
await db.upsert_from_chunks_async(chunks_by_document)
Get Chunk Embeddings:
# Retrieve embeddings for specific chunks
embeddings = db.get_chunk_embeddings(["chunk1", "chunk2"])
# Returns numpy array of shape (n_chunks, embedding_dim)
Search and Query Operations
Unified Query Interface:
# Vector search (semantic)
results = db.query(
query="machine learning algorithms",
search_type="vector",
k=10,
filters={"year": {"$gte": 2020}}
)
# Keyword search (FTS)
results = db.query(
query="exact phrase match",
search_type="keyword",
k=10
)
# Hybrid search (combined)
results = db.query(
query="neural networks",
search_type="hybrid",
k=10,
vector_weight=0.5 # 50% vector, 50% keyword (keyword weight = 1 - vector_weight)
)
# Async variants
results = await db.query_async(query, **kwargs)
# Hierarchical search (server database created with hierarchical_embeddings=True)
results = db.query(
query="how do I rotate the API key?",
search_level="sections", # "chunks" (default), "sections", or "documents"
)
# ...or section-grouped results from the chunk index:
results = db.query(query="billing", return_type="sections")
RemoteVectorDB.query accepts the same search_level="sections"/
"documents" and return_type="sections" options as the local database; see
Hierarchical Embeddings. The options are forwarded to the server, which must host a
database created with hierarchical_embeddings=True.
Note
search_level="fused" is not available on remote databases — a fused
query on RemoteVectorDB raises NotImplementedError (the server query
route does not accept it). Use a local LocalVectorDB
for fused retrieval.
Multi-Column Search:
# Search the main content plus embedding-enabled metadata columns.
# Pass a single query string and the columns to search (use "content"
# for the main document text). If columns is omitted, all
# embedding-enabled fields plus the main content are searched.
results = db.query_multi_column(
"neural networks",
columns=["content", "title", "abstract"],
search_type="vector",
k=10
)
# Async variant
results = await db.query_multi_column_async(
"neural networks", columns=["content", "title", "abstract"]
)
MongoDB-style Filtering:
# Filter documents with complex conditions
docs = db.filter(
where={
"author": "Alice",
"year": {"$gte": 2020, "$lt": 2025},
"tags": {"$in": ["AI", "ML"]},
"$or": [
{"published": True},
{"internal_review": "approved"}
]
},
order_by="year DESC",
limit=20,
offset=0
)
# Async variant
docs = await db.filter_async(where, **kwargs)
Metadata Operations
Update Metadata Schema:
from localvectordb.core import MetadataField, MetadataFieldType
# Add new metadata fields
new_schema = {
'new_field': MetadataField(
type=MetadataFieldType.TEXT,
indexed=True
),
'score': MetadataField(
type=MetadataFieldType.REAL,
indexed=True,
default_value=0.0
)
}
db.update_metadata_schema(
new_schema,
drop_columns=False # Keep columns removed from the schema (safe default)
)
# Async variant
await db.update_metadata_schema_async(new_schema, drop_columns=False)
Get Schema Information:
# Retrieve current metadata schema
schema_info = db.get_metadata_schema_info()
# Returns: {
# "fields": {...},
# "field_count": 5,
# "indexed_fields": [...],
# "required_fields": [...],
# "field_types": {...}
# }
# Async variant
schema_info = await db.get_metadata_schema_info_async()
Database Tuning Operations
RemoteVectorDB inherits from TuningMixin, providing remote access to SQLite tuning:
# Get current tuning settings
settings = db.get_sqlite_tuning()
# Apply tuning profile
db.set_sqlite_tuning(
profile="fast_ingest", # or "balanced", "read_optimized", "durable", "memory_saver"
overrides={"cache_size": -262144} # 256MB cache
)
# Maintenance operations
db.sqlite_checkpoint(mode="FULL") # WAL checkpoint
db.sqlite_optimize() # Optimize query planner
db.sqlite_vacuum() # Reclaim space
db.sqlite_incremental_vacuum(pages=1000) # Incremental cleanup
# System analysis
resources = db.analyze_system_resources()
# Conditional checkpoint
was_checkpointed = db.checkpoint_if_wal_large(wal_mb_threshold=128)
Database Management
Get Statistics:
stats = db.get_stats()
# Returns: {
# "total_documents": 10000,
# "total_chunks": 50000,
# "vector_dim": 768,
# "db_size_mb": 1024.5,
# "indexes": [...],
# ...
# }
# Async variant
stats = await db.get_stats_async()
Health Checks:
# Check if server is healthy (property, not a method)
is_healthy = db.healthy
# Ping server (with caching)
is_alive = db.ping(force=False) # Uses cached result if recent
is_alive = db.ping(force=True) # Forces new ping
Connection Management:
# Check if connection is closed (property, not a method)
is_closed = db.closed
# Save any pending changes
db.save()
await db.save_async()
# Close connection and cleanup
db.close()
await db.close_async()
Context Manager Support:
# Automatic cleanup with context manager
with RemoteVectorDB("mydb", "http://localhost:8000") as db:
db.upsert(documents)
results = db.query("search")
# Connection automatically closed
# Async context manager
async with RemoteVectorDB("mydb", "http://localhost:8000") as db:
await db.upsert_async(documents)
results = await db.query_async("search")
Async Operations
Every method in RemoteVectorDB has an async variant for high-performance applications:
Basic Async Pattern
All async methods follow the naming convention of adding _async suffix:
import asyncio
from localvectordb.client import RemoteVectorDB
async def main():
db = RemoteVectorDB("mydb", "http://localhost:8000")
# Async document operations
doc_ids = await db.upsert_async(["Doc 1", "Doc 2"])
doc = await db.get_async(doc_ids[0])
await db.update_async(doc_ids[0], content="Updated")
await db.delete_async(doc_ids)
# Async search
results = await db.query_async("search term", k=5)
# Async schema management
await db.update_metadata_schema_async(updates)
# Cleanup
await db.close_async()
asyncio.run(main())
Concurrent Operations
Leverage async for concurrent operations:
async def process_batch(db, batch_data):
tasks = []
# Create concurrent upsert tasks
for content, metadata in batch_data:
task = db.upsert_async([content], [metadata])
tasks.append(task)
# Execute all upserts concurrently
doc_ids_lists = await asyncio.gather(*tasks)
return [ids[0] for ids in doc_ids_lists]
Async Context Manager
Use async context manager for automatic cleanup:
async def search_documents():
async with RemoteVectorDB("mydb", "http://localhost:8000") as db:
# Concurrent searches
results = await asyncio.gather(
db.query_async("machine learning", search_type="vector"),
db.query_async("machine learning", search_type="keyword"),
db.filter_async({"author": "Alice"})
)
return results
# Connection automatically closed
Code Examples
Migration from Local to Remote
Here’s how to migrate existing LocalVectorDB code to RemoteVectorDB:
Original Local Code:
from localvectordb import LocalVectorDB
from localvectordb.core import MetadataField, MetadataFieldType
# Local database
db = LocalVectorDB(
name="products",
base_path="./data",
metadata_schema={
'category': MetadataField(type=MetadataFieldType.TEXT, indexed=True),
'price': MetadataField(type=MetadataFieldType.REAL, indexed=True)
}
)
# Operations
db.upsert(["Product A", "Product B"], metadata=[...])
results = db.query("electronics", filters={"price": {"$lt": 1000}})
Migrated to Remote (Option 1: Direct):
from localvectordb.client import RemoteVectorDB
from localvectordb.core import MetadataField, MetadataFieldType
# Remote database - same API!
db = RemoteVectorDB(
name="products",
base_url="https://vectordb.company.com",
api_key="your-api-key",
metadata_schema={
'category': MetadataField(type=MetadataFieldType.TEXT, indexed=True),
'price': MetadataField(type=MetadataFieldType.REAL, indexed=True)
}
)
# Exact same operations work!
db.upsert(["Product A", "Product B"], metadata=[...])
results = db.query("electronics", filters={"price": {"$lt": 1000}})
Migrated to Remote (Option 2: Using Factory):
from localvectordb import VectorDB
from localvectordb.core import MetadataField, MetadataFieldType
import os
# Environment-based configuration
# Development: DB_PATH="./data"
# Production: DB_PATH="https://vectordb.company.com"
db = VectorDB(
name="products",
base_path=os.getenv("DB_PATH", "./data"),
api_key=os.getenv("LVDB_API_KEY"), # Only used if remote
metadata_schema={
'category': MetadataField(type=MetadataFieldType.TEXT, indexed=True),
'price': MetadataField(type=MetadataFieldType.REAL, indexed=True)
}
)
# Same operations for both local and remote!
db.upsert(["Product A", "Product B"], metadata=[...])
results = db.query("electronics", filters={"price": {"$lt": 1000}})
RAG Application Example
Build a Retrieval-Augmented Generation system:
from localvectordb import VectorDB
from localvectordb.core import MetadataField, MetadataFieldType
import os
class RAGSystem:
def __init__(self, db_path: str):
# Works with both local and remote databases
self.db = VectorDB(
name="knowledge_base",
base_path=db_path,
api_key=os.getenv("LVDB_API_KEY"),
metadata_schema={
'source': MetadataField(type=MetadataFieldType.TEXT, indexed=True),
'section': MetadataField(type=MetadataFieldType.TEXT, indexed=True),
'last_updated': MetadataField(type=MetadataFieldType.DATE, indexed=True)
},
embedding_model="nomic-embed-text",
chunk_size=512,
chunk_overlap=50
)
def add_documents(self, file_paths: list, source: str):
"""Add documents from files"""
metadata = [{"source": source} for _ in file_paths]
return self.db.upsert_from_file(file_paths, metadata=metadata)
def retrieve_context(self, query: str, max_docs: int = 5):
"""Retrieve relevant context for a query"""
results = self.db.query(
query=query,
search_type="hybrid",
k=max_docs,
vector_weight=0.5
)
contexts = []
for result in results:
contexts.append({
'content': result.content,
'source': result.metadata.get('source', 'Unknown'),
'score': result.score
})
return contexts
async def retrieve_context_async(self, query: str, max_docs: int = 5):
"""Async version for high-performance scenarios"""
results = await self.db.query_async(
query=query,
search_type="hybrid",
k=max_docs,
vector_weight=0.5
)
# Process results...
return contexts
# Usage - works identically for local and remote!
# Development
rag = RAGSystem("./local_data")
# Production
rag = RAGSystem("https://vectordb.company.com")
# Add knowledge base
rag.add_documents(["doc1.pdf", "doc2.md"], source="technical_docs")
# Retrieve context
contexts = rag.retrieve_context("How does the system handle errors?")
Document Processing Pipeline
Process documents with metadata extraction:
import asyncio
from datetime import datetime
from localvectordb import VectorDB
class DocumentProcessor:
def __init__(self, db_url: str):
self.db = VectorDB("documents", db_url)
async def process_document_batch(self, documents: list):
"""Process documents in parallel"""
tasks = []
for doc in documents:
task = self.process_single_document(doc)
tasks.append(task)
results = await asyncio.gather(*tasks, return_exceptions=True)
successful = [r for r in results if not isinstance(r, Exception)]
failed = [r for r in results if isinstance(r, Exception)]
return {
'successful': len(successful),
'failed': len(failed),
'errors': failed
}
async def process_single_document(self, doc: dict):
"""Process a single document"""
# Extract metadata
metadata = {
'title': doc.get('title', 'Untitled'),
'author': doc.get('author', 'Unknown'),
'processed_at': datetime.now().isoformat(),
'word_count': len(doc['content'].split()),
'language': doc.get('language', 'en')
}
# Upsert to database
doc_id = await self.db.upsert_async(
documents=[doc['content']],
metadata=[metadata],
ids=[doc.get('id')]
)
return doc_id[0]
async def search_recent(self, query: str, days: int = 7):
"""Search recently processed documents"""
from datetime import datetime, timedelta
cutoff_date = (datetime.now() - timedelta(days=days)).isoformat()
results = await self.db.query_async(
query=query,
search_type="hybrid",
filters={
"processed_at": {"$gte": cutoff_date}
},
k=20
)
return results
Error Handling
RemoteVectorDB provides comprehensive error handling:
Exception Types
from localvectordb.exceptions import (
DatabaseNotFoundError,
DocumentNotFoundError,
DuplicateDocumentIDError,
EmbeddingError,
DatabaseError
)
try:
db = RemoteVectorDB("nonexistent", "http://localhost:8000")
except DatabaseNotFoundError as e:
print(f"Database not found: {e}")
try:
doc = db.get("missing_id")
except DocumentNotFoundError as e:
print(f"Document not found: {e}")
try:
db.insert(["content"], ids=["existing_id"])
except DuplicateDocumentIDError as e:
print(f"Document already exists: {e}")
Retry Logic
RemoteVectorDB includes automatic retry with exponential backoff:
db = RemoteVectorDB(
name="mydb",
base_url="http://localhost:8000",
max_retries=3, # Retry failed requests up to 3 times
retry_delay=1.0 # Base delay, exponentially increases
)
# Requests will automatically retry on:
# - Network errors
# - 5xx server errors
# - Timeout errors
Connection Health Monitoring
Monitor and handle connection health:
import time
def ensure_healthy_connection(db: RemoteVectorDB):
"""Ensure database connection is healthy"""
if db.closed: # property, not a method
raise RuntimeError("Database connection is closed")
if not db.ping():
# Try to wait and retry
time.sleep(1)
if not db.ping(force=True):
raise RuntimeError("Database server is not responding")
if not db.healthy: # property, not a method
raise RuntimeError("Database is not healthy")
return True
Performance Optimization
Connection Pooling
Optimize connection reuse:
from httpx import Limits
# Configure connection pooling for high-throughput
db = RemoteVectorDB(
name="mydb",
base_url="http://localhost:8000",
connection_pool_limits=Limits(
max_keepalive_connections=50, # Keep more connections alive
max_connections=200, # Allow more total connections
keepalive_expiry=60.0 # Keep connections alive longer
),
max_concurrent_requests=20 # More concurrent embedding requests
)
Batch Operations
Use batch operations for efficiency:
# Inefficient: Multiple round trips
for doc in documents:
db.upsert([doc['content']], [doc['metadata']])
# Efficient: Single batch operation
contents = [doc['content'] for doc in documents]
metadata = [doc['metadata'] for doc in documents]
db.upsert(contents, metadata)
Async Concurrency
Leverage async for parallel operations:
async def parallel_search(db, queries):
"""Execute multiple searches in parallel"""
tasks = [
db.query_async(query, k=10)
for query in queries
]
results = await asyncio.gather(*tasks)
return results
Use Appropriate Search Types
Choose the right search type for your use case:
# Fast: Keyword search for exact matches
results = db.query("ERROR: Connection failed", search_type="keyword")
# Accurate: Vector search for semantic similarity
results = db.query("network connectivity issues", search_type="vector")
# Balanced: Hybrid for best of both
results = db.query("connection problems", search_type="hybrid")
Database URI Support
RemoteVectorDB supports URI-based connections:
from localvectordb.factory import from_uri
# Local database
db = from_uri("lvdb:///path/to/databases/mydb")
# Remote HTTP
db = from_uri("lvdb+http://localhost:8000/mydb")
# Remote HTTPS with auth
db = from_uri("lvdb+https://api_key@vectordb.company.com/mydb")
# With query parameters
db = from_uri(
"lvdb+https://vectordb.company.com/mydb?"
"chunk_size=1000&embedding_model=nomic-embed-text"
)
Best Practices
Use Environment Variables for Configuration
Store sensitive configuration in environment variables:
# .env file VECTOR_DB_URL=https://vectordb.company.com LVDB_API_KEY=sk-abc123def456 # Application code db = VectorDB( "mydb", os.getenv("VECTOR_DB_URL"), api_key=os.getenv("LVDB_API_KEY") )
Implement Health Checks
Monitor database health in production:
async def health_check(): try: if not db.healthy: # property, not a method alert_ops_team("Database unhealthy") return False return True except Exception as e: alert_ops_team(f"Health check failed: {e}") return False
Use Context Managers
Ensure proper cleanup with context managers:
async def process_documents(): async with RemoteVectorDB("mydb", url) as db: # Process documents await db.upsert_async(documents) # Connection automatically closed
Handle Errors Gracefully
Implement comprehensive error handling:
from localvectordb.exceptions import BaseLocalVectorDBException try: results = db.query("search term") except BaseLocalVectorDBException as e: logger.error(f"Database operation failed: {e}") # Implement fallback logic except Exception as e: logger.critical(f"Unexpected error: {e}") # Alert and fail safely
Optimize for Your Use Case
High Write Throughput: Use batch operations and async upserts
Low Latency Queries: Keep connection pools warm, use caching
Large Documents: Use file operations with chunking
Complex Filtering: Create appropriate indexes on metadata fields
See Also
Quickstart - Get started with LocalVectorDB
Server - Deploy LocalVectorDB server
Query Types and Return Modes - Query methods and options
Metadata Filtering Guide - Metadata schema and filtering
Embeddings - Embedding providers configuration
Performance Tuning Guide - Performance tuning guide