> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cyborg.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Query

Retrieves the nearest neighbors for given query vectors.

```cpp theme={null}
QueryResults Query(Array2D<float>& query_vectors,
                   const QueryParams& query_params,
                   const KeyContext& key);
```

### Parameters

| Parameter       | Type                                  | Description                                                                                                                                                                                                 |
| --------------- | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `query_vectors` | [`Array2D<float>`](../types#array2d)  | Query vectors to search.                                                                                                                                                                                    |
| `query_params`  | [`QueryParams`](../types#queryparams) | Parameters for querying, such as `top_k`, `n_probes`, and `rerank_mult` (default 50). Pass `cyborg::QueryParams{}` for defaults.                                                                            |
| `key`           | [`KeyContext`](../types#keycontext)   | Key context for the operation. A bare 32-byte index key (the `index_key`) implicitly converts to a `KeyContext`. For an RBAC user, pass `cyborg::KeyContext{user_kek, user_id}` (read permission required). |

<Note>Both `query_params` and `key` are required. There are no longer default values for these arguments.</Note>

<Tip>If this function is called on an index where `TrainIndex()` has not been executed (or while a retrain is in progress), the query will use encrypted exhaustive search.
This may cause queries to be slower, especially when there are many vector embeddings in the index.</Tip>

### Returns

[`QueryResults`](../types#queryresults): Results `top_k` containing decrypted nearest neighbors IDs and distances.

### Exceptions

<AccordionGroup>
  <Accordion title="std::invalid_argument">
    * Throws if the query vectors have incompatible dimensions with the index.
    * Throws if the index was not created or loaded yet.
  </Accordion>

  <Accordion title="std::runtime_error">
    * Throws if the query could not be executed.
    * Throws if the supplied key context lacks read permission.
  </Accordion>
</AccordionGroup>

### Example Usage

```cpp theme={null}
cyborg::Array2D<float> queries{/*...*/}; // Populate with one or more query vectors

// Query with default parameters
QueryResults results = index->Query(queries, cyborg::QueryParams{}, index_key);

// Query with explicit parameters: top_k = 10, n_probes = 5
cyborg::QueryParams params(10, 5);
QueryResults results2 = index->Query(queries, params, index_key);

auto view = results[0]; // Access first query's results
for (uint32_t j = 0; j < view.num_results; ++j) {
    std::cout << "ID: " << view.ids[j] << ", Distance: " << view.distances[j] << std::endl;
}
```

<Tip>`index_key` is the 32-byte `std::array<uint8_t, 32>` index KEK and converts implicitly to a `KeyContext`. In a stateless service that reloads the index per request, pass the key on every operation.</Tip>
