# Query with $vectorSearch
```js
db.docs.aggregate([
{ $vectorSearch: {
index: "vec_idx",
path: "embedding",
queryVector: embeddingArray, // floats from your embedding model
numCandidates: 200, // ANN beam width, 10-20x limit is a good start
limit: 10,
filter: { tenantId: "t1" } // only fields indexed as type "filter"
} },
{ $project: { text: 1, score: { $meta: "vectorSearchScore" } } }
]);
```
## Rules
- `$vectorSearch` must be the FIRST stage in the pipeline. Anything before it is an error.
- `queryVector` length must equal the index `numDimensions`. Count it before you send it.
- `numCandidates` trades recall for latency. Start at 10 to 20 times `limit` and tune from measured recall, not vibes.
- `filter` only works on fields declared `type: "filter"` in the index. Filtering on anything else requires a `$match` after, which applies post top-k.
- Get the relevance score with `{ $meta: "vectorSearchScore" }` in a later `$project`. There is no score without it.
- For hybrid search, run `$vectorSearch` and `$search` in separate pipelines and fuse ranks in code (reciprocal rank fusion). There is no single stage that does both.
## Verify
Run the pipeline with a known-similar document and confirm it ranks first with a sane score.