import vantadb_py as vantadb
from typing import List, Dict, Any, Optional, Union
import json
import os
DB_PATH = "./haystack_vantadb_db"
class VantaDBDocumentStore:
def __init__(self, db_path: str = DB_PATH, namespace: str = "haystack/documents"):
self.db = vantadb.VantaDB(db_path, memory_limit_bytes=1_000_000_000)
self.namespace = namespace
def write_documents(
self,
documents: List[Dict[str, Any]],
batch_size: int = 100
) -> int:
count = 0
for doc in documents:
doc_id = doc.get("id") or f"doc-{count}"
content = doc.get("content", "")
meta = doc.get("meta", {})
vector = doc.get("embedding")
meta["_document_id"] = doc_id
self.db.put(
self.namespace,
doc_id,
content,
metadata=meta,
vector=vector
)
count += 1
return count
def get_documents_by_id(
self,
ids: List[str],
return_embedding: bool = False
) -> List[Dict[str, Any]]:
documents = []
for doc_id in ids:
record = self.db.get(self.namespace, doc_id)
if record:
doc = {
"id": record["key"],
"content": record["payload"],
"meta": record["metadata"]
}
if return_embedding:
doc["embedding"] = record.get("vector")
documents.append(doc)
return documents
def get_document_by_id(
self,
id: str,
return_embedding: bool = False
) -> Optional[Dict[str, Any]]:
docs = self.get_documents_by_id([id], return_embedding)
return docs[0] if docs else None
def query(
self,
query: str,
query_vector: Optional[List[float]] = None,
filters: Optional[Dict[str, Any]] = None,
top_k: int = 10,
return_embedding: bool = False
) -> List[Dict[str, Any]]:
search_filters = filters or {}
hits = self.db.search_memory(
self.namespace,
query_vector=query_vector,
text_query=query,
top_k=top_k,
filters=search_filters
)
documents = []
for hit in hits:
record = hit["record"]
doc = {
"id": record["key"],
"content": record["payload"],
"meta": record["metadata"],
"score": hit["score"]
}
if return_embedding:
doc["embedding"] = record.get("vector")
documents.append(doc)
return documents
def delete_documents(
self,
ids: Optional[List[str]] = None,
filters: Optional[Dict[str, Any]] = None
) -> int:
if ids:
count = 0
for doc_id in ids:
if self.db.delete(self.namespace, doc_id):
count += 1
return count
if filters:
records = self.db.list(self.namespace, {"limit": 1000, "filters": filters})
count = 0
for record in records:
if self.db.delete(self.namespace, record["key"]):
count += 1
return count
return 0
def get_document_count(self) -> int:
records = self.db.list(self.namespace, {"limit": 1000000})
return len(records)
def get_all_documents(
self,
filters: Optional[Dict[str, Any]] = None,
return_embedding: bool = False,
batch_size: int = 100
) -> List[Dict[str, Any]]:
records = self.db.list(self.namespace, {"limit": 1000000, "filters": filters or {}})
documents = []
for record in records:
doc = {
"id": record["key"],
"content": record["payload"],
"meta": record["metadata"]
}
if return_embedding:
doc["embedding"] = record.get("vector")
documents.append(doc)
return documents
def update_document(
self,
id: str,
content: Optional[str] = None,
meta: Optional[Dict[str, Any]] = None,
embedding: Optional[List[float]] = None
) -> bool:
existing = self.db.get(self.namespace, id)
if not existing:
return False
new_content = content or existing["payload"]
new_meta = meta or existing["metadata"]
new_vector = embedding or existing.get("vector")
self.db.put(
self.namespace,
id,
new_content,
metadata=new_meta,
vector=new_vector
)
return True
def close(self):
self.db.flush()
self.db.close()
def main():
store = VantaDBDocumentStore(namespace="haystack/documents")
print("๐ Writing documents...")
documents = [
{
"id": "doc-001",
"content": "VantaDB is an embedded persistent memory and vector retrieval engine for local-first AI applications.",
"meta": {"category": "database", "type": "description"}
},
{
"id": "doc-002",
"content": "Haystack is an open-source NLP framework that enables developers to build powerful NLP applications.",
"meta": {"category": "framework", "type": "description"}
},
{
"id": "doc-003",
"content": "Vector databases enable efficient similarity search for high-dimensional embeddings.",
"meta": {"category": "database", "type": "concept"}
},
{
"id": "doc-004",
"content": "RAG (Retrieval-Augmented Generation) combines retrieval with generation for better AI responses.",
"meta": {"category": "ai", "type": "concept"}
}
]
count = store.write_documents(documents)
print(f" Written {count} documents")
print("\n๐ Querying for 'vector database'...")
results = store.query("vector database", top_k=3)
for i, doc in enumerate(results, 1):
print(f" [{i}] Score: {doc['score']:.3f}")
print(f" ID: {doc['id']}")
print(f" Content: {doc['content'][:80]}...")
print(f" Meta: {doc['meta']}")
print("\n๐ Querying with metadata filter (category=framework)...")
results = store.query("", filters={"category": "framework"})
for doc in results:
print(f" ID: {doc['id']}")
print(f" Content: {doc['content'][:80]}...")
print(f"\n๐ Total documents: {store.get_document_count()}")
print("\n๐งน Cleaning up...")
store.close()
if os.path.exists(DB_PATH):
import shutil
shutil.rmtree(DB_PATH)
print("Database cleaned up.")
if __name__ == "__main__":
main()