Vectors alone are not enough
A vector database stores an embedding (a list of numbers) for each chunk so you can find semantically similar text. But pure similarity search is blunt: you often need to restrict results to a user, a date range, a document type, or a language. That is what JSON metadata attached to each vector is for — and designing it well separates a demo from a production RAG system.
The anatomy of a stored record
Each record is typically an id, the embedding, and a JSON metadata object:
{
"id": "doc_42#chunk_3",
"values": [0.012, -0.34, 0.91],
"metadata": {
"text": "Refunds are processed within 5-7 business days.",
"source": "refund-policy",
"doc_type": "policy",
"lang": "en",
"tenant_id": "acme",
"updated": "2026-04-01"
}
}Most vector databases let you store the chunk text in metadata so a single query returns both the match and the content to feed the model.
Metadata filtering
The key feature: combine semantic search with structured filters so you only search relevant vectors.
{
"vector": [0.1, 0.2, 0.3],
"top_k": 5,
"filter": {
"tenant_id": "acme",
"doc_type": "policy",
"updated": { "$gte": "2026-01-01" }
}
}This finds the five most similar chunks only among Acme's policy documents updated this year. Filtering first keeps results relevant and secure — critical for multi-tenant apps where one customer must never see another's data.
Design metadata for the queries you will run
- Include every field you might filter on: tenant, source, language, category, date.
- Use the right types. Store dates as ISO strings or timestamps so range filters work; store enums as short strings.
- Keep it small. Metadata is stored per vector; bloated objects cost memory and money. Store the chunk text plus filter fields, not the entire original document.
- Index high-cardinality filters carefully. Some stores require declaring which metadata fields are filterable.
Hybrid search: vectors + keywords
Pure vector search can miss exact terms (product codes, names). Hybrid search combines semantic similarity with keyword (BM25) matching and merges the scores. Your JSON metadata carries the keyword fields, and the engine blends both rankings — giving you the recall of semantics and the precision of exact matches.
Multi-tenancy and security
Never rely on the application layer alone to isolate tenants. Put tenant_id (or user_id) in metadata and always include it in the filter. A leaked vector is a data breach, so make tenant filtering a non-optional part of every query in your retrieval code.