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

Finds the nearest neighbors of one or more query vectors. With `query_contents`, the service embeds the text first (the index needs an `embedding_model`). With `text`, the query becomes **hybrid**: BM25 full-text ranking is fused with the vector ranking.

```python theme={null}
# Single vector
index.query(query_vectors=vector, top_k=10)

# Batch of vectors
index.query(query_vectors=vectors, top_k=10)

# Text, embedded by the service
index.query(query_contents=text, top_k=10)

# Hybrid (BM25 + vector); needs an index with a full-text field
index.query(query_vectors=vector, text="encrypted search", top_k=10)
```

### Parameters

| Parameter | Type | Default | Description |
| - | - | - | - |
| `query_vectors` | `List[float]`, `List[List[float]]`, or `np.ndarray` | `None` | *(Optional)* One query vector, or a batch. A NumPy array is sent through the binary path, [`query_binary()`](./query-binary). |
| `query_contents` | `str` | `None` | *(Optional)* Text for the service to embed and search with. Requires an index created with `embedding_model`. Ignored when `query_vectors` is a NumPy array. |
| `top_k` | `int` | `None` (service default: `100`) | *(Optional)* Results to return per query. Must be at least `1`. |
| `n_probes` | `int` | `None` (service default: auto) | *(Optional)* Clusters to probe. Higher values improve recall and add latency. |
| `filters` | `Dict` | `None` | *(Optional)* Metadata filter. See [Metadata filtering](../types#metadata-filtering). |
| `include` | `List[str]` | `None` (service default: `[]`) | *(Optional)* Extra fields per result: `"distance"` and `"metadata"`. `id` is always returned. See [Result fields](#result-fields). |
| `greedy` | `bool` | `None` (service default: `False`) | *(Optional)* Use greedy search. |
| `rerank_mult` | `int` | `None` (service default: `50`) | *(Optional)* Stage 1 returns `top_k * rerank_mult` candidates before reranking narrows them to `top_k`. Higher values trade latency for recall. |
| `text` | `str` | `None` | *(Optional)* Query text for a BM25 leg, which makes the query hybrid. Requires an index with at least one full-text field. `query_vectors` is still required. |
| `text_fields` | `List[str]` | `None` (all full-text fields) | *(Optional)* Full-text fields the BM25 leg searches. Naming a field that isn't full-text returns `ValidationError`. |
| `text_field_weights` | `List[float]` | `None` (`1.0` each) | *(Optional)* Weight per searched field, in the same order as `text_fields`. |
| `require_all_terms` | `bool` | `None` (service default: `False`) | *(Optional)* Match only items containing every query term (AND) instead of any term (OR). |
| `alpha` | `float` | `None` (service default: `0.5`) | *(Optional)* Blend of the two legs, in `[0, 1]`: `0` is pure BM25, `1` is pure vector. At exactly `0` or `1` the other leg isn't run. |
| `rrf_k` | `float` | `None` (service default: `60`) | *(Optional)* Reciprocal rank fusion smoothing constant. Must be `> 0`. |
| `window_mult` | `int` | `None` (service default: `3`) | *(Optional)* Candidates retrieved per leg, as a multiple of `top_k`. Must be `>= 1`. |

### Returns

* **Single query vector:** `List[Dict]`, one dict per neighbor.
* **Batch of two or more vectors:** `List[List[Dict]]`, one inner list per query vector.

A query with exactly one vector always returns single results, even when it's sent as a batch or through the binary path.

#### Result fields

```python theme={null}
{
    "id": str,        # Always returned
    "distance": float, # Vector queries, when "distance" is in include. Lower is closer.
    "score": float,    # Hybrid queries only, instead of distance. Higher is more relevant.
    "metadata": Dict,  # When "metadata" is in include
}
```

`query()` never returns `vector` or `contents`, even when they're listed in `include`. To read them, pass the result IDs to [`get()`](./get).

### Exceptions

<AccordionGroup>
  <Accordion title="pydantic.ValidationError">
    Neither `query_vectors` nor `query_contents` is passed. Raised before any request is sent.
  </Accordion>

  <Accordion title="cyborgdb.ValidationError">
    * A NumPy `query_vectors` array is not 1-D or 2-D. Raised before any request is sent.
    * The service rejects the query (HTTP `400`/`422`): wrong vector dimension, `text` on an index without full-text fields, or an out-of-range `alpha`, `rrf_k`, or `window_mult`. Other numeric parameters aren't range-checked.
  </Accordion>

  <Accordion title="cyborgdb.AuthenticationError">
    The `index_key` or `api_key` is invalid (HTTP `401`).
  </Accordion>

  <Accordion title="cyborgdb.ServiceError / cyborgdb.TransportError">
    The service returns `5xx` or can't be reached.
  </Accordion>
</AccordionGroup>

See [Errors](../errors) for the full hierarchy.

### Example Usage

#### Single vector

```python theme={null}
results = index.query(
    query_vectors=[0.1, 0.2, 0.3, 0.4],
    top_k=2,
    include=["distance", "metadata"],
)

for result in results:
    print(result["id"], round(result["distance"], 4), result["metadata"])
# Output:
# doc1 0.0 {'category': 'news'}
# doc2 0.8 {'category': 'research'}
```

#### Batch of vectors

```python theme={null}
batch_results = index.query(
    query_vectors=[
        [0.1, 0.2, 0.3, 0.4],
        [0.5, 0.6, 0.7, 0.8],
    ],
    top_k=1,
    include=["distance"],
)

for i, results in enumerate(batch_results):
    print(i, [r["id"] for r in results])
# Output:
# 0 ['doc1']
# 1 ['doc2']
```

#### Text, embedded by the service

```python theme={null}
# The index must have been created with embedding_model=...
results = index.query(
    query_contents="machine learning in healthcare",
    top_k=3,
)
print([r["id"] for r in results])
```

#### Hybrid (BM25 + vector)

The index needs at least one full-text field, set with `text_fields` or `{"full_text": True}` in [`create_index()`](../client/create-index#metadata-schema).

```python theme={null}
results = index.query(
    query_vectors=[0.1, 0.2, 0.3, 0.4],
    text="encrypted search",
    top_k=2,
    alpha=0.5,
    include=["metadata"],
)

for result in results:
    print(result["id"], round(result["score"], 4))
# Output:
# doc1 0.0164
# doc2 0.0161
```

#### Filters and search options

```python theme={null}
results = index.query(
    query_vectors=[0.1, 0.2, 0.3, 0.4],
    top_k=20,
    n_probes=5,
    rerank_mult=20,
    greedy=True,
    filters={"category": "news"},
    include=["distance", "metadata"],
)

for result in results:
    print(result["id"], result["metadata"]["category"])
# Output: doc1 news
```


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