RUNLOCALAIv38
->Will it run?Best GPUCompareTroubleshootStartLearnPulseModelsHardwareToolsBench
Run check
RUNLOCALAI

Independently operated catalog for local-AI hardware and software. Hand-written verdicts. Source-cited claims. Reproducible commands when we have them.

OP·Eruo Fredoline
DIR
  • Models
  • Hardware
  • Tools
  • Benchmarks
TOOLS
  • Will it run?
  • Compare hardware
  • Cost vs cloud
  • Choose my GPU
  • Prompting kits
  • Quick answers
REF
  • All buyer guides
  • Learn local AI
  • Methodology
  • Glossary
  • Errors KB
  • Trust
EDITOR
  • About
  • Author
  • How we make money
  • Editorial policy
  • Contact
LEGAL
  • Privacy
  • Terms
  • Sitemap
MAIL · MONTHLY DIGEST
Get monthly local AI changes
Monthly recap. No spam.
DISCLOSURE

Some links on this site are affiliate links (Amazon Associates and other first-class retailers). When you buy through them, we earn a small commission at no extra cost to you. Affiliate links do not influence our verdicts — there are cards we rate highly that we don't have affiliate relationships with, and cards that sell well that we refuse to recommend. Read more →

© 2026 runlocalai.coIndependently operated
RUNLOCALAI · v38
  1. >
  2. Home
  3. /Learn
  4. /How-to
  5. /How to Implement Metadata Filtering in ChromaDB
HOW-TO · RAG

How to Implement Metadata Filtering in ChromaDB

intermediate·15 min·By Eruo Fredoline
Target environment
Ubuntu 24.04 · Ollama 0.4.x
PREREQUISITES

ChromaDB with documents containing metadata

What this does

ChromaDB supports filtering retrieved documents by metadata key-value pairs at query time. This guide explains how to structure metadata when adding documents and how to apply filters such as equality, range comparisons, and compound conditions during similarity search.

Steps

  1. Add documents with structured metadata. Use flat key-value pairs with supported types (string, int, float, bool).

    import chromadb
    
    client = chromadb.PersistentClient(path="./filtered_db")
    col = client.get_or_create_collection(name="filtered_docs")
    
    col.add(
        ids=["p1", "p2", "p3", "p4"],
        documents=[
            "Deploying ChromaDB on Docker improves scalability.",
            "Metadata filtering speeds up retrieval in large corpora.",
            "Ollama supports quantized models for edge devices.",
            "RAG pipelines reduce hallucinations in LLM outputs."
        ],
        metadatas=[
            {"category": "infra", "year": 2024, "rating": 4.5},
            {"category": "rag", "year": 2024, "rating": 4.8},
            {"category": "ai", "year": 2023, "rating": 4.2},
            {"category": "rag", "year": 2025, "rating": 4.9}
        ]
    )
    print("Indexed:", col.count())
    
  2. Filter by exact string match.

    results = col.query(
        query_texts=["retrieval performance"],
        where={"category": "rag"},  # exact match filter
        n_results=2
    )
    for doc, meta in zip(results["documents"][0], results["metadatas"][0]):
        print(f"[{meta['category']}] {doc}")
    
  3. Filter by numeric range.

    results = col.query(
        query_texts=["reliability and quality"],
        where={"rating": {"$gte": 4.5}},  # rating >= 4.5
        n_results=3
    )
    for doc, meta in zip(results["documents"][0], results["metadatas"][0]):
        print(f"[rating: {meta['rating']}] {doc}")
    
  4. Combine multiple filter conditions.

    results = col.query(
        query_texts=["deployment"],
        where={
            "category": "infra",
            "rating": {"$gte": 4.0}
        },
        n_results=5
    )
    print("Filtered results:", len(results["documents"][0]))
    

Verification

python3 -c "
import chromadb
c = chromadb.PersistentClient(path='/tmp/chroma_filter_test')
col = c.get_or_create_collection('filt')
col.add(ids=['a','b'], documents=['doc a','doc b'], metadatas=[{'tag':'x'},{'tag':'y'}])
r = col.query(query_texts=['doc'], where={'tag':'x'}, n_results=1)
print('Filter result:', r['documents'][0])
c.delete_collection('filt')
"
# Expected: Filter result: ['doc a']

Common failures

  • Filter key not in metadata. Applying where={"nonexistent_field": "value"} returns zero results silently, not an error. Always verify the metadata schema when debugging empty results.
  • Wrong filter operator syntax. $gte, $gt, $lte, $lt must be inside a dict for the value, not at the top level. Writing {"rating": 4.5} instead of {"rating": {"$gte": 4.5}} performs equality, not range comparison.
  • Non-string keys in metadata. Metadata values can be strings, numbers, or bools, but keys must be strings. Passing {"2024": "value"} as metadata keys causes a type error.
  • Large result sets with no filter. Omitting where on a large collection returns all top-k matches sorted by vector distance, ignoring metadata. Always include explicit filters for scoped queries.
  • Metadata updated without re-embedding. Modifying metadata via update_metadata does not change the vector. The document stays at the same embedding location; filtering still works correctly.

Related guides

  • create-manage-chromadb-collections
  • enable-chromadb-persistence-production
RELATED GUIDES
RAG
How to Create and Manage ChromaDB Collections
RAG
How to Enable ChromaDB Persistence for Production
← All how-to guidesCourses →