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

## Single Query

Retrieves the nearest neighbors for a given query vector. Passing `text` alongside `query_vectors` turns this into a **hybrid** query that fuses BM25 full-text ranking with the vector ranking (see [Full-text and hybrid search](../../guides/data-operations/bm25-search)).

```python theme={null}
def query(self,
          query_vectors: List[float] = None,
          query_contents: str = None,
          top_k: int = None,
          n_probes: int = None,
          filters: Dict[str, Any] = None,
          include: List[str] = None,
          greedy: bool = False,
          rerank_mult: int = None,
          *,
          text: str = None,
          text_fields: List[str] = None,
          text_field_weights: List[float] = None,
          require_all_terms: bool = False,
          alpha: float = None,
          rrf_k: float = None,
          window_mult: int = None,
          index_key: bytes,
          user_id: bytes = None)
```

### Parameters

| Parameter | Type | Default | Description |
| - | - | - | - |
| `query_vectors` | `List[float]` | - | A single query vector as a list of floats (for single query). |
| `query_contents` | `str` | `None` | *(Optional)* Text content to auto-embed as query vector (requires `embedding_model` set during index creation). |
| `top_k` | `int` | `None` | *(Optional)* Number of nearest neighbors to return. When `None`, defaults to 100. |
| `n_probes` | `int` | `None` | *(Optional)* Number of lists probed during the query; higher values may increase recall but can also reduce performance. When `None` or `0`, automatically determines the optimal value. |
| `filters` | `Dict[str, Any]` | `None` | *(Optional)* A dictionary of filters to apply to vector metadata, limiting search scope to these vectors. |
| `include` | `List[str]` | `None` | *(Optional)* List of item fields to return. Can include `distance` and `metadata`. When empty, only IDs are returned. |
| `greedy` | `bool` | `False` | *(Optional)* Whether to use greedy search (higher recall with same `n_probes`). |
| `rerank_mult` | `int` | `50` | *(Optional)* Stage-1 retrieval multiplier for reranking. The index retrieves `rerank_mult * top_k` candidates before reranking them against the stored vectors to produce the final `top_k`. Higher values improve recall at some cost to performance. |
| `text` | `str` | `None` | *(Optional, keyword-only)* Query text for a BM25 full-text leg. Setting it makes the query **hybrid**: BM25 ranking is fused with the vector ranking by weighted RRF and each result carries `score` instead of `distance`. Requires an index with at least one `full_text` field. |
| `text_fields` | `List[str]` | `None` | *(Optional, keyword-only)* Which `full_text` fields the text leg searches. `None` = all designated fields. Naming a non-`full_text` field raises. |
| `text_field_weights` | `List[float]` | `None` | *(Optional, keyword-only)* Per-field weights on the summed per-field BM25 scores, parallel to the searched fields. `None` = 1.0 each. |
| `require_all_terms` | `bool` | `False` | *(Optional, keyword-only)* Require every query term to match (AND) instead of any (OR, the default). |
| `alpha` | `float` | `None` (default `0.5`) | *(Optional, keyword-only)* Leg blend in `[0, 1]`: `0` = pure BM25, `1` = pure vector. An exact endpoint skips the dead leg's retrieval. |
| `rrf_k` | `float` | `None` (default `60`) | *(Optional, keyword-only)* RRF rank-smoothing constant (must be `> 0`). Higher rewards agreement further down each leg's list. |
| `window_mult` | `int` | `None` (default `3`) | *(Optional, keyword-only)* Per-leg candidate depth as a **multiple of `top_k`** (must be `>= 1`), so each leg looks deeper than the final cut. |
| `index_key` | `bytes` | - | *(Required, keyword-only)* 32-byte index KEK. See [Index key](#index-key). |
| `user_id` | `bytes` | `None` | *(Optional, keyword-only)* 16-byte RBAC user identifier. See [Index key](#index-key). |

<Note>If embedding auto-generation is enabled (by setting the `embedding_model` parameter in [`create_index()`](../client/create-index), then the `query_contents` parameter can be used instead of `query_vectors`.</Note>

<Note>Hybrid queries **still require a query vector** — including at `alpha=0`, where it only fixes the batch shape. For text search with no vector at all, use [`query_metadata(text=...)`](./query-metadata).</Note>

<Tip>`filters` use a subset of the [MongoDB Query and Projection Operators](https://www.mongodb.com/docs/manual/reference/operator/query/).
For instance: `filters: { "$and": [ { "label": "cat" }, { "confidence": { "$gte": 0.9 } } ] }` means that only vectors where `label == "cat"` and `confidence >= 0.9` will be considered for encrypted vector search.
For more info on metadata, see [Metadata Filtering](../../guides/data-operations/metadata-filtering).</Tip>

<Note>Hybrid queries narrow which filters are accepted. `$regex` on a non-`pattern` field, and any predicate on an explicitly non-`filterable` field, work in a pure `query()` but are rejected once `text` is set, because the text leg can only be filtered on fields resolvable from the encrypted metadata index. Move the filter to a `pattern` / `filterable` field or drop `text`.</Note>

### Returns

`List[Dict[str, Union[int, float, Dict[]]]]`: List of results for the query vector. Each result is a list of `top_k` dictionaries, each containing `id` (always included), and optionally `distance` (pure vector query), `score` (hybrid query — fused BM25 + vector relevance, larger = more relevant), and `metadata` based on `include`. A hybrid result carries `score` in place of `distance` — never both, since a text-only match has no vector distance. When `include` is empty (the default), only `id` is returned.

### Exceptions

<AccordionGroup>
  <Accordion title="ValueError">
    * Throws if the query vector has incompatible dimensions with the index.
    * Throws if the index was not created or loaded yet.
    * Throws if `text` is passed but the index has no `full_text` field.
    * Throws if `text_fields` names a field that is not `full_text`.
    * Throws if any `text_*` knob is set without a non-empty `text`.
    * Throws if `rrf_k <= 0` or `window_mult < 1` is passed explicitly (pass `None` for defaults).
    * Throws if a filter references a field the index cannot resolve when `text` is set (e.g. `$regex` on a non-`pattern` field, or any predicate on an explicitly non-`filterable` field).
    * Throws if the query could not be executed.
  </Accordion>

  <Accordion title="EmbeddingModelUnavailable">
    * Throws if `query_contents` needs embedding and the index's built-in model cannot be downloaded or loaded (offline cache miss, network failure). Often transient.
  </Accordion>
</AccordionGroup>

### Example Usage

*Single Query with Distances*:

```python theme={null}
# Load index
index = client.load_index(
    index_name=index_name, 
    index_key=index_key
)

# Define a single query vector
query_vectors = [0.1, 0.2, 0.3]  # Single query vector of dimension 3

# Perform a single query with distances
results = index.query(
    query_vectors=query_vectors, 
    top_k=2, 
    n_probes=5, 
    include=["distance"],
    index_key=index_key
)
# Example output:
# [{"id": "101", "distance": 0.05}, {"id": "102", "distance": 0.1}]
```

*Hybrid Query (BM25 + Vector)*:

Requires an index created with at least one `full_text` field (see [Full-text and hybrid search](../../guides/data-operations/bm25-search)).

```python theme={null}
# text=... turns this into a hybrid query. A query vector is still required.
results = index.query(
    query_vectors=[0.1, 0.2, 0.3],
    text="encrypted search",
    top_k=10,
    alpha=0.5,              # 0 = pure BM25, 1 = pure vector; default 0.5
    include=["metadata"],
    index_key=index_key,
)
# Hybrid results carry `score` (fused relevance, higher = better) instead of `distance`.
# Example output:
# [{"id": "a1", "score": 0.0161, "metadata": {...}}, ...]
```

*Single Query without Distances*:

```python theme={null}
results = index.query(
    query_vectors=query_vectors, 
    top_k=10, 
    n_probes=5, 
    include=[],
    index_key=index_key
)
# Example output:
# [{"id": "101"}, {"id": "102"}]
```

*Single Query with Metadata*:

```python theme={null}
results = index.query(
    query_vectors=query_vectors, 
    top_k=10, 
    n_probes=5, 
    filters={"label": "dog"}, 
    include=["metadata"],
    index_key=index_key
)
# Example output:
# [{"id": "101", "metadata": {"label": "dog", "temperament": "good boy"}},
#  {"id": "102", "metadata": {"label": "dog", "temperament": "hyper"})]]
```

Results are plain dictionaries — access fields by string key (`r['id']`, `r['distance']`, `r['metadata']`):

```python theme={null}
for r in results:
    print(r['id'], r['distance'])
```

### Index key

`index_key` is required on every call. Pass the same 32-byte index KEK you used with [`create_index()`](../client/create-index) / [`load_index()`](../client/load-index). For an [RBAC user](./manage-users), pass the user's KEK as `index_key=` together with their `user_id=`:

```python theme={null}
results = index.query(
    query_vectors=[0.1, 0.2, 0.3],
    top_k=2,
    index_key=user_kek,
    user_id=user_id,
)
```

## Batched Queries

Retrieves the nearest neighbors for one or more query vectors.

```python theme={null}
def query(self,
          query_vectors: Union[np.ndarray, List[List[float]]],
          query_contents: Union[str, List[str]] = None,
          top_k: int = None,
          n_probes: int = None,
          filters: Dict[str, Any] = None,
          include: List[str] = None,
          greedy: bool = False,
          rerank_mult: int = None,
          *,
          index_key: bytes,
          user_id: bytes = None)
```

### Parameters

| Parameter | Type | Default | Description |
| - | - | - | - |
| `query_vectors` | `np.ndarray` or `List[List[float]]` | - | A 2D NumPy array or list of lists, where each inner list represents a query vector (for batch query). |
| `query_contents` | `str` or `List[str]` | `None` | *(Optional)* Text content to auto-embed as query vectors (requires `embedding_model` set during index creation). A list is a batch. |
| `top_k` | `int` | `None` | *(Optional)* Number of nearest neighbors to return. When `None`, defaults to 100. |
| `n_probes` | `int` | `None` | *(Optional)* Number of lists probed during the query; higher values may increase recall but can also reduce performance. When `None` or `0`, automatically determines the optimal value. |
| `filters` | `Dict[str, Any]` | `None` | *(Optional)* A dictionary of filters to apply to vector metadata, limiting search scope to these vectors. |
| `include` | `List[str]` | `None` | *(Optional)* List of item fields to return. Can include `distance` and `metadata`. When empty, only IDs are returned. |
| `greedy` | `bool` | `False` | *(Optional)* Whether to use greedy search (higher recall with same `n_probes`). |
| `rerank_mult` | `int` | `50` | *(Optional)* Stage-1 retrieval multiplier for reranking. The index retrieves `rerank_mult * top_k` candidates before reranking them against the stored vectors to produce the final `top_k`. Higher values improve recall at some cost to performance. |
| `index_key` | `bytes` | - | *(Required, keyword-only)* 32-byte index KEK. See [Index key](#index-key). |
| `user_id` | `bytes` | `None` | *(Optional, keyword-only)* 16-byte RBAC user identifier. See [Index key](#index-key). |

<Tip>`filters` use a subset of the [MongoDB Query and Projection Operators](https://www.mongodb.com/docs/manual/reference/operator/query/).
For instance: `filters: { "$and": [ { "label": "cat" }, { "confidence": { "$gte": 0.9 } } ] }` means that only vectors where `label == "cat"` and `confidence >= 0.9` will be considered for encrypted vector search.
For more info on metadata, see [Metadata Filtering](../../guides/data-operations/metadata-filtering).</Tip>

<Note>Batched queries accept the same BM25 keyword-only params as the single-query form (`text`, `text_fields`, `text_field_weights`, `require_all_terms`, `alpha`, `rrf_k`, `window_mult`); the same `text` value applies to every row in the batch.</Note>

### Returns

`List[List[Dict[str, Union[int, float, Dict[]]]]]`: List of results for each query vector. Each result is a list of `top_k` dictionaries, each containing `id` (always included), and optionally `distance` (pure vector query), `score` (hybrid query), and `metadata` based on `include`. When `include` is empty (the default), only `id` is returned.

### Exceptions

<AccordionGroup>
  <Accordion title="ValueError">
    * Throws if the query vectors have incompatible dimensions with the index.
    * Throws if the index was not created or loaded yet.
    * Throws if the query could not be executed.
  </Accordion>
</AccordionGroup>

### Example Usage

*Batch Query with Distances*:

```python theme={null}
import numpy as np

# Multiple query vectors
query_vectors = np.array([
    [0.1, 0.2, 0.3],
    [0.4, 0.5, 0.6]
])

# Query with distances included
results = index.query(query_vectors=query_vectors, include=["distance"], index_key=index_key)
# Example output:
# [
#     [{"id": "item_101", "distance": 0.05}, {"id": "item_202", "distance": 0.1}],
#     [{"id": "item_202", "distance": 0.2}, {"id": "item_303", "distance": 0.3}]
# ]
```

***

## NumPy Query

A high-performance query variant that returns only integer IDs as a NumPy array. This is optimized for performance-critical workloads where metadata and distances are not needed.

```python theme={null}
def query_numpy(self,
                query_vectors: np.ndarray,
                top_k: int = 100,
                n_probes: int = 0,
                greedy: bool = False,
                batch: bool = False,
                rerank_mult: int = 50,
                *,
                index_key: bytes,
                user_id: bytes = None) -> np.ndarray
```

### Parameters

| Parameter | Type | Default | Description |
| - | - | - | - |
| `query_vectors` | `np.ndarray` | - | Query vectors as a NumPy array. For a single query, a 1D array; for batch queries, a 2D array. |
| `top_k` | `int` | `100` | *(Optional)* Number of nearest neighbors to return. |
| `n_probes` | `int` | `0` (auto) | *(Optional)* Number of lists probed during the query. When set to `0`, automatically determines the optimal value. |
| `greedy` | `bool` | `False` | *(Optional)* Whether to use greedy search (higher recall with same `n_probes`). |
| `batch` | `bool` | `False` | *(Optional)* Whether to treat the input as a batch of query vectors. |
| `rerank_mult` | `int` | `50` | *(Optional)* Stage-1 retrieval multiplier for reranking (retrieves `rerank_mult * top_k` candidates before reranking). |
| `index_key` | `bytes` | - | *(Required, keyword-only)* 32-byte index KEK. See [Index key](#index-key). |
| `user_id` | `bytes` | `None` | *(Optional, keyword-only)* 16-byte RBAC user identifier. |

### Returns

`np.ndarray`: A NumPy array of integer IDs for the nearest neighbors. For a single query, returns a 1D array of shape `(top_k,)`. For batch queries, returns a 2D array of shape `(num_queries, top_k)`. Slots beyond the number of results found, and IDs that cannot be converted to integers, are set to `-1`.

### Exceptions

<AccordionGroup>
  <Accordion title="ValueError">
    * Throws if the query vectors have incompatible dimensions with the index.
    * Throws if the index was not created or loaded yet.
    * Throws if the query could not be executed.
  </Accordion>

  <Accordion title="TypeError">
    * Throws if the `query_vectors` format does not match the `batch` parameter.
  </Accordion>
</AccordionGroup>

### Example Usage

```python theme={null}
import numpy as np

# Single query
query_vector = np.array([0.1, 0.2, 0.3], dtype=np.float32)
ids = index.query_numpy(query_vectors=query_vector, top_k=10, index_key=index_key)
# ids is a 1D np.ndarray of integer IDs, e.g. array([101, 102, 103, ...])

# Batch query
query_vectors = np.array([
    [0.1, 0.2, 0.3],
    [0.4, 0.5, 0.6]
], dtype=np.float32)
ids = index.query_numpy(query_vectors=query_vectors, top_k=5, batch=True, index_key=index_key)
# ids is a 2D np.ndarray of shape (2, 5)
```

<Note>`query_numpy` is a high-performance variant that returns only integer IDs. Use the standard `query()` method if you need distances, metadata, or string IDs.</Note>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.