2.1.3. Storing Embeddings and Vector Similarity Search
💡 First Principle: Cosmos DB treats vectors as a special data class because the geometry from Section 1.1.2 demands special machinery: embeddings are large (poison for the standard index) and searched by distance, not equality (needing a purpose-built index). Declare what your vectors look like once, and the engine builds the right machinery around them.
Vector search arrives in a container through a vector embedding policy, defined at container creation: the path holding the vector, its data type, its dimensionality, and the distance function used to compare vectors:
{
"vectorEmbeddings": [{
"path": "/embedding",
"dataType": "float32",
"dimensions": 1536,
"distanceFunction": "cosine"
}]
}
This policy is fixed at creation — you can't later change dimensions or distance function for that path, so it must match your embedding model up front. Alongside the policy, you choose a vector index type, and this choice is the exam's favorite vector question because it's the exact/approximate trade-off from 1.1.2 wearing Azure clothes:
| Index type | Method | Accuracy | Scale | Choose when |
|---|---|---|---|---|
| flat | Brute-force exact scan | Exact | Small collections (dim ≤ ~505) | Accuracy is non-negotiable, data is small |
| quantizedFlat | Compressed vectors, exact-style scan | Near-exact | Larger (dim ≤ ~4096) | Good accuracy, lower RU/latency than flat |
| diskANN | Graph-based ANN | Approximate (high recall) | Large collections | Production RAG at scale |
Querying uses the VectorDistance system function with ORDER BY — and combines naturally with metadata filters:
SELECT TOP 5 c.content, VectorDistance(c.embedding, @queryVector) AS score
FROM c
WHERE c.category = "refund-policy"
ORDER BY VectorDistance(c.embedding, @queryVector)
The WHERE clause narrows candidates before ranking by distance — the same metadata-filtered RAG pattern you'll meet again in PostgreSQL (2.2.4).
Two housekeeping rules complete the picture. First — echoing 2.1.2 — add the vector path to excludedPaths in the standard indexing policy; a 1536-float array in the general index bloats every write for zero benefit. Second, float32 is the standard dataType for typical embedding models.
⚠️ Exam Trap: Forgetting to exclude /embedding/* from the regular indexing policy is the classic "writes suddenly cost a fortune" scenario. The vector index and the standard index are separate mechanisms; the embedding path belongs in the first and out of the second.
Reflection Question: Your RAG collection has grown from 10K to 10M documents and flat-index queries are slow and RU-hungry. Which index type do you migrate to, and what do you knowingly give up?