Querying & Filtering
From the course ChromaDB: Local Vector Database
Querying ChromaDB
Semantic Search
results = collection.query(
query_texts=["What causes rain?"],
n_results=5,
include=["documents", "metadatas", "distances"]
)
Metadata Filtering
results = collection.query(
query_texts=["machine learning"],
n_results=10,
where={"topic": "technology"},
where_document={"$contains": "neural"}
)
Filter Operators
# Comparison
where={"year": {"$gt": 2023}}
where={"price": {"$lte": 50}}
# Logical
where={"$and": [
{"category": "science"},
{"year": {"$gte": 2023}}
]}
where={"$or": [
{"status": "published"},
{"status": "featured"}
]}
Updating & Deleting
# Update documents
collection.update(
ids=["doc1"],
documents=["Updated content"],
metadatas=[{"topic": "updated"}]
)
# Delete by ID
collection.delete(ids=["doc1", "doc2"])
# Delete by filter
collection.delete(where={"status": "archived"})
Common Pitfall: Forgetting to Include Metadata at Upsert Time
You cannot add metadata to a document after it has been inserted without calling update(). If you add 10,000 documents and forget the metadatas parameter, you'll need to update every record individually — an expensive operation. Always plan your metadata schema before bulk ingestion and add it upfront.
Best Practice: Use upsert Instead of add
For pipelines that re-index documents regularly, prefer collection.upsert() over collection.add(). The add method raises an error if an ID already exists, while upsert creates or updates as needed. This makes your ingestion pipeline idempotent:
# Idempotent ingestion — safe to re-run
collection.upsert(
documents=["Updated content here"],
ids=["doc1"],
metadatas=[{"version": 2, "updated_at": "2025-01-01"}],
)
Advanced Filter Example: Date Range Query
A common real-world pattern is filtering documents by recency while also doing semantic search:
import time
one_week_ago = int(time.time()) - 7 * 86400
results = collection.query(
query_texts=["machine learning breakthroughs"],
n_results=5,
where={
"$and": [
{"published_ts": {"$gte": one_week_ago}},
{"source": {"$in": ["arxiv", "blog"]}},
]
},
)
Store Unix timestamps as integers in metadata — ChromaDB's filter operators work on numeric types but not ISO date strings.
Key Takeaways
- •Query with text (auto-embedded) or raw vectors
- •Combine semantic search with metadata and document content filters
- •Use logical operators ($and, $or) for complex filter conditions
- •Update and delete operations support both ID and filter-based targeting
Progress is kept in this browser only.