DatabaseHandle
DatabaseHandle provides all operations scoped to a single database. Obtain an instance via
LocalVectorDBClient:
const db = client.database("my_database");
Database Info
const info = await db.info();
console.log(info.name, info.stats, info.config);
Document Operations
Upsert Documents
Insert or update documents. If a document with the same ID exists, it is replaced.
// Single document
const { ids } = await db.upsert("Hello world");
// Multiple documents with metadata
const result = await db.upsert(
["Document one", "Document two"],
{
metadata: [
{ author: "Alice", year: 2024 },
{ author: "Bob", year: 2023 },
],
ids: ["doc-1", "doc-2"],
batch_size: 100,
}
);
Insert Documents
Like upsert, but fails if a document with the same ID already exists:
// Strict insert — throws DuplicateDocumentError on conflict
await db.insert(["New document"], { ids: ["unique-id"] });
// Ignore duplicates instead of throwing
await db.insert(["Maybe new"], { ids: ["maybe-exists"], errors: "ignore" });
Get Documents
// Single document — returns Document
const doc = await db.get("doc-1");
console.log(doc.id, doc.content, doc.metadata);
// Multiple documents — returns Document[]
const docs = await db.get(["doc-1", "doc-2"]);
Update a Document
await db.update("doc-1", {
content: "Updated content",
metadata: { author: "Alice Smith", revised: true },
});
Delete Documents
// Single document — uses HTTP DELETE
await db.delete("doc-1");
// Batch delete — uses POST
const { deleted_count, failed_ids } = await db.delete(["doc-1", "doc-2", "doc-3"]);
Count Documents
// Count all documents
const total = await db.count();
// Count with metadata filter
const filtered = await db.count({ filters: { author: "Alice" } });
Check Existence
const { exists, ids } = await db.exists(["doc-1", "doc-2"]);
// exists: [true, false] — positional, aligned with ids (["doc-1", "doc-2"])
if (exists[0]) {
console.log(`${ids[0]} exists`);
}
List Documents
const page = await db.list({ offset: 0, limit: 20 });
console.log(page.documents.length, page.pagination);
Chunked Documents
If you have already chunked your documents externally, you can insert them directly:
await db.upsertChunks({
"doc-1": ["chunk 1 of doc 1", "chunk 2 of doc 1"],
"doc-2": ["chunk 1 of doc 2"],
});
await db.insertChunks(
{ "doc-3": ["chunk a", "chunk b"] },
{ errors: "ignore" }
);
Search Operations
Unified Query
The query() method supports vector, keyword, and hybrid search:
// Vector search (default)
const results = await db.query("semantic meaning");
// Keyword search
const kw = await db.query("exact terms", { search_type: "keyword" });
// Hybrid search with tuned weighting
const hybrid = await db.query("machine learning", {
search_type: "hybrid",
vector_weight: 0.5, // 50% vector, 50% keyword
k: 10,
score_threshold: 0.3,
});
// With metadata filters
const filtered = await db.query("neural networks", {
search_type: "hybrid",
filters: { author: "Alice", year: { "$gte": 2023 } },
return_type: "chunks",
});
Multi-Column Query
Search across specific metadata columns that have embeddings enabled:
const results = await db.queryMultiColumn("python data science", {
columns: ["content", "summary"],
search_type: "hybrid",
});
Filter by Metadata
MongoDB-style metadata filtering without a search query:
// Simple equality
const docs = await db.filter({ author: "Alice" });
// Advanced operators
const recent = await db.filter(
{
year: { "$gte": 2023 },
category: { "$in": ["ml", "ai"] },
},
{
order_by: "year DESC",
limit: 10,
offset: 0,
}
);
Streaming
See Streaming Queries for the full streaming guide. Quick example:
for await (const result of db.queryStream("search text", { k: 50 })) {
console.log(result.id, result.score);
}
Schema Management
// Get current schema
const schema = await db.getSchema();
// Add or modify fields
await db.updateSchema(
{
category: { type: "text", indexed: true },
rating: { type: "real", indexed: true },
},
{ drop_columns: false }
);
Embeddings
Retrieve embeddings for existing chunk IDs or generate them for custom text:
// By chunk IDs
const byId = await db.getEmbeddings({ ids: ["chunk-id-1", "chunk-id-2"] });
// By text
const byText = await db.getEmbeddings({ texts: ["custom text to embed"] });
// byId.embeddings / byText.embeddings: number[][]
Document Comparison
Compare Documents
// Quick similarity score
const { similarity } = await db.compare("doc-1", "doc-2");
console.log(`Similarity: ${(similarity * 100).toFixed(1)}%`);
// Detailed chunk-level comparison
const detailed = await db.compareDetailed("doc-1", "doc-2", {
chunk_threshold: 0.7,
});
Nearest Neighbors
const { results } = await db.nearestNeighbors("doc-1", 5);
for (const r of results) {
console.log(`${r.id}: ${r.score.toFixed(3)}`);
}
Similarity Matrix
// All documents
const matrix = await db.similarityMatrix();
// Specific subset
const subset = await db.similarityMatrix(["doc-1", "doc-2", "doc-3"]);
// subset.matrix: number[][] (3x3 pairwise similarities)
Tuning & Maintenance
// Get current SQLite tuning
const tuning = await db.getTuning();
// Apply a tuning profile
// (valid profiles: balanced, fast_ingest, read_optimized, durable, memory_saver)
await db.setTuning("fast_ingest", { persist: true });
// Maintenance operations
await db.checkpoint("PASSIVE");
await db.optimize();
await db.vacuum();
await db.incrementalVacuum(2000);
// Checkpoint only if WAL is large
await db.checkpointIfWalLarge(128); // threshold in MB
// Auto-tuning recommendations (workload is a structured profile object;
// every field is optional and falls back to balanced defaults)
const recs = await db.autoTune({ workload: { workload_type: "read_heavy" } });
// Apply recommendations automatically
await db.autoTune({
workload: { workload_type: "read_heavy", memory_constraint: "generous" },
apply: true,
});
QueryOptions Reference
Property |
Type |
Default |
Description |
|---|---|---|---|
|
|
|
Search strategy |
|
|
|
Result granularity |
|
|
|
Maximum results to return |
|
|
|
Minimum score (0–1) |
|
|
MongoDB-style metadata filters |
|
|
|
|
Weight of vector score in hybrid search (0–1) |
|
|
|
Size of the assembled context for |
|
|
|
How |
|
|
|
With a budget unit, hard-truncate the assembled context to exactly the budget (otherwise it may fall short by up to one chunk) |
|
|
|
How to aggregate chunk scores to document scores |