Home / AI & GenAI / Vector Databases

AI & GenAICheat sheetBeginner

Chroma cheat sheet: clients, collections, add/upsert, query with where and where_document filters, and housekeeping

The Chroma Python API on one page - choosing a client, creating collections with an explicit distance, add vs upsert, query and get with metadata and document filters, includes, updates, deletes, counts and the errors you'll hit most.

Deepak Bhardwaj4 min read

Applies toChroma 0.5-1.x Python client (chromadb); configuration syntax shown for 1.x with 0.x metadata equivalents

Clients

Client Use
chromadb.EphemeralClient() In-memory; tests
chromadb.PersistentClient(path="./chroma") Embedded with local storage; single process
chromadb.HttpClient(host="chroma", port=8000) Client-server; production
chromadb.AsyncHttpClient(...) async apps (await calls)
import chromadb
client = chromadb.HttpClient(host="chroma.internal", port=8000)
client.heartbeat()
client.get_version()

Collections

col = client.get_or_create_collection(
    name="kb_chunks",
    configuration={"hnsw": {"space": "cosine", "ef_construction": 200, "ef_search": 100}},  # 1.x
    # 0.x: metadata={"hnsw:space": "cosine"}
    embedding_function=None,      # None if you always pass your own embeddings
)

client.list_collections()
client.get_collection("kb_chunks")
client.delete_collection("kb_chunks")
col.count()
col.peek(5)                       # first few items
col.modify(name="kb_chunks_old")  # rename

Collection names: 3–512 characters, letters, digits, ., _, -; must start and end with a letter or digit.

Add, upsert, update

col.add(
    ids=["doc42#0", "doc42#1"],
    embeddings=[emb0, emb1],
    documents=["chunk text 0", "chunk text 1"],
    metadatas=[{"doc_id": "doc42", "source": "wiki", "year": 2026},
               {"doc_id": "doc42", "source": "wiki", "year": 2026}],
)
col.upsert(ids=[...], embeddings=[...], documents=[...], metadatas=[...])   # insert or replace
col.update(ids=["doc42#0"], metadatas=[{"doc_id": "doc42", "reviewed": True}])
  • add with an existing ID doesn't overwrite it; use upsert for idempotent ingestion.
  • If you omit embeddings, Chroma embeds documents with the collection's embedding function.
  • Metadata values: str, int, float, bool (newer versions add array support; check your version). No None, no nested dicts.
  • Very large batches can hit the server's maximum batch size: client.get_max_batch_size() (newer versions) tells you the limit.

Query

res = col.query(
    query_embeddings=[qvec],
    n_results=10,
    where={"source": "wiki"},
    where_document={"$contains": "VPN"},
    include=["documents", "metadatas", "distances"],
)
for i, d, m, dist in zip(res["ids"][0], res["documents"][0], res["metadatas"][0], res["distances"][0]):
    print(i, round(dist, 3), m["doc_id"])

Results are lists per query embedding, hence [0]. include options: documents, metadatas, distances, embeddings (embeddings are large; include only when needed).

Metadata filters (where)

Operator Example
Equal {"source": "wiki"} or {"source": {"$eq": "wiki"}}
Not equal {"status": {"$ne": "archived"}}
Greater / less {"year": {"$gte": 2025}}, $gt, $lt, $lte
In / not in {"source": {"$in": ["wiki", "jira"]}}, $nin
AND {"$and": [{"source": "wiki"}, {"year": {"$gte": 2025}}]}
OR {"$or": [{"source": "wiki"}, {"source": "jira"}]}

A where with two keys at the top level ({"a": 1, "b": 2}) raises an error; use $and.

Document filters (where_document)

Operator Example
Contains substring {"$contains": "ORA-01555"}
Doesn't contain {"$not_contains": "deprecated"}
Regex (newer versions) {"$regex": "KB50[0-9]{5}"}
Combine {"$and": [{"$contains": "VPN"}, {"$not_contains": "legacy"}]}

$contains is case-sensitive substring matching, not ranked full-text search.

col.get(ids=["doc42#0"], include=["documents", "metadatas"])
col.get(where={"doc_id": "doc42"}, include=["metadatas"])
col.get(limit=500, offset=1000, include=["embeddings"])      # paging for exports

Delete

col.delete(ids=["doc42#0", "doc42#1"])
col.delete(where={"doc_id": "doc42"})

Caution

In some versions col.delete() with neither ids nor where could delete everything or raise; never call it without arguments. To empty a collection, delete and recreate it.

Distances

Space Value Similarity
l2 (default) Squared L2 lower is better
cosine 1 − cosine similarity 1 - distance
ip 1 − dot product 1 - distance

Set space explicitly when creating a collection; it can't be changed later.

Common errors

Error Cause / fix
Collection [x] does not exist Name typo; tenant/database mismatch on the client
Embedding dimension 3072 does not match collection dimensionality 1536 Wrong model; one model per collection
Expected where to have exactly one operator Two keys at top level; wrap in $and
Expected metadata value to be a str, int, float or bool None or nested value in metadata
Batch size ... exceeds maximum batch size Split batches
Client/server API errors after upgrade Client and server versions differ

Tenants and databases

The server has tenants and databases (defaults default_tenant / default_database). Pass them when you use more than the default:

client = chromadb.HttpClient(host="chroma", port=8000, tenant="team-a", database="kb")

Prevent mistakes next time

  • Use upsert with deterministic IDs (doc_id#chunk).
  • Set space explicitly; pass query_embeddings from the same model as ingestion.
  • Keep metadata flat and typed; no None.
  • Never call delete() without a selector.