data-infra
Glossary ↗Metadata Filtering
Metadata filtering is the practice of attaching structured attributes (metadata) — like a date, a category, a user ID, a status flag, a price — to each vector stored in a vector database, and then constraining a similarity search to only consider vectors whose metadata matches specified filter conditions, alongside the semantic similarity ranking itself. It answers a query pattern that pure vector similarity search can't handle alone: "find the passages most similar to this question, but only from documents published after 2025 and tagged `product: enterprise`." Why it matters for AI/SaaS builders: nearly every real-world RAG or semantic-search feature needs this. A support-desk AI shouldn't surface an outdated article that's been superseded; a multi-tenant app must never return another customer's data no matter how semantically similar it is; a marketplace search needs to combine "find products like this" with "only show ones in stock and under $50." Vector similarity alone is oblivious to all of these business-logic constraints — it only knows about meaning, not about access control, recency, or inventory state — so metadata filtering is the mechanism that reconnects semantic search to the real, structured constraints every production application actually has. How it works: at insert/upsert time, each vector is stored alongside a metadata object (commonly JSON: `{"category": "billing", "published": true, "date": "2026-03-14", "tenant_id": "t_88"}`). At query time, the application passes both the query vector and a filter expression (syntax varies by vector database — Pinecone uses a Mongo-style operator syntax like `{"tenant_id": {"$eq": "t_88"}, "date": {"$gte": "2026-01-01"}}`; pgvector, being plain Postgres, uses ordinary SQL `WHERE` clauses alongside the `ORDER BY embedding <=> $1`). Some vector databases apply the filter before the ANN search (pre-filtering, which can be slower if the filter is very selective and the index has to search harder to find enough matches within a narrow subset) while others apply it after (post-filtering, which can return fewer than `top_k` results if too many top matches get filtered out) — the trade-off is implementation-specific and worth checking in a given database's docs when precision matters. Worked example: a job-board SaaS's AI-powered candidate search embeds resumes and lets recruiters search in natural language ("senior backend engineer with Kubernetes experience"), but a recruiter should only ever see candidates who opted into being searchable and who are located in their hiring region. The query combines vector similarity with a filter: `{"opted_in": true, "region": {"$in": ["EU", "UK"]}, "years_experience": {"$gte": 5}}` — ensuring the semantically-best matches returned are also the only ones the recruiter is legally and contractually allowed to see.
Related terms