# 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.