> ## 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 `queryContents`, the service embeds the text first (the index needs an `embeddingModel`). With `text`, the query becomes **hybrid**: BM25 full-text ranking is fused with the vector ranking.

```typescript theme={null}
async query({
    queryVectors?: number[] | number[][] | Float32Array,
    queryContents?: string,
    topK?: number,
    nProbes?: number,
    filters?: FilterExpression,
    include?: string[],
    greedy?: boolean,
    rerankMult?: number,
    dimension?: number,
    text?: string,
    textFields?: string[],
    textFieldWeights?: number[],
    requireAllTerms?: boolean,
    alpha?: number,
    rrfK?: number,
    windowMult?: number,
}): Promise<QueryResponse>
```

### Parameters

| Parameter | Type | Default | Description |
| - | - | - | - |
| `queryVectors` | `number[]`, `number[][]`, or `Float32Array` | `undefined` | *(Optional)* One query vector, a batch, or a batch packed back to back in a `Float32Array` (sent in a faster binary format). |
| `queryContents` | `string` | `undefined` | *(Optional)* Text for the service to embed and search with. Requires an index created with `embeddingModel`. |
| `topK` | `number` | `undefined` (service default: `100`) | *(Optional)* Results to return per query. Must be at least `1`. |
| `nProbes` | `number` | `undefined` (service default: auto) | *(Optional)* Clusters to probe. Higher values improve recall and add latency. |
| `filters` | [`FilterExpression`](../types#filterexpression) | `undefined` | *(Optional)* Metadata filter. See [Metadata filtering](../types#metadata-filtering). |
| `include` | `string[]` | `undefined` (service default: `[]`) | *(Optional)* Extra fields per result: `'distance'` and `'metadata'`. `id` is always returned. See [Result fields](#result-fields). |
| `greedy` | `boolean` | `undefined` (service default: `false`) | *(Optional)* Use greedy search. |
| `rerankMult` | `number` | `undefined` (service default: `50`) | *(Optional)* Stage 1 returns `topK * rerankMult` candidates before reranking narrows them to `topK`. Higher values trade latency for recall. |
| `dimension` | `number` | `undefined` | Required when `queryVectors` is a `Float32Array`, to split it into vectors. Ignored otherwise. |
| `text` | `string` | `undefined` | *(Optional)* Query text for a BM25 leg, which makes the query hybrid. Requires an index with at least one full-text field. `queryVectors` is still required. |
| `textFields` | `string[]` | `undefined` (all full-text fields) | *(Optional)* Full-text fields the BM25 leg searches. Naming a field that isn't full-text throws `CyborgDBValidationError`. |
| `textFieldWeights` | `number[]` | `undefined` (`1.0` each) | *(Optional)* Weight per searched field, in the same order as `textFields`. |
| `requireAllTerms` | `boolean` | `undefined` (service default: `false`) | *(Optional)* Match only items containing every query term (AND) instead of any term (OR). |
| `alpha` | `number` | `undefined` (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. |
| `rrfK` | `number` | `undefined` (service default: `60`) | *(Optional)* Reciprocal rank fusion smoothing constant. Must be `> 0`. |
| `windowMult` | `number` | `undefined` (service default: `3`) | *(Optional)* Candidates retrieved per leg, as a multiple of `topK`. Must be `>= 1`. |

### Returns

`Promise<QueryResponse>`, whose `results` is:

* **One `number[]` query vector:** `QueryResultItem[]`, one item per neighbor.
* **Two or more query vectors** (`number[][]` or `Float32Array`): `QueryResultItem[][]`, one inner array 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.

`QueryResponse.results` is typed `QueryResultItem[] | QueryResultItem[][]`. Since the call shape decides which one you get, narrow it with a cast: `response.results as QueryResultItem[]` for one vector, or `as QueryResultItem[][]` for a batch.

#### Result fields

```typescript theme={null}
{
    id: string,         // Always returned
    distance?: number,  // Vector queries, when 'distance' is in include. Lower is closer.
    score?: number,     // Hybrid queries only, instead of distance. Higher is more relevant.
    metadata?: object,  // 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="CyborgDBValidationError">
    * Neither `queryVectors` nor `queryContents` is passed, or a `Float32Array` is passed without `dimension`. Thrown 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`, `rrfK`, or `windowMult`. Other numeric parameters aren't range-checked.
  </Accordion>

  <Accordion title="CyborgDBAuthenticationError">
    The `indexKey` or `apiKey` is invalid (HTTP `401`).
  </Accordion>

  <Accordion title="CyborgDBServiceError">
    The service returns `5xx`.
  </Accordion>
</AccordionGroup>

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

### Example Usage

#### Single vector

```typescript theme={null}
import type { QueryResultItem } from 'cyborgdb';

const response = await index.query({
    queryVectors: [0.1, 0.2, 0.3, 0.4],
    topK: 2,
    include: ['distance', 'metadata'],
});
const results = response.results as QueryResultItem[];

for (const r of results) {
    console.log(r.id, Number(r.distance?.toFixed(4)), r.metadata);
}
// Output:
// doc1 0 { category: 'news' }
// doc2 0.8 { category: 'research' }
```

#### Batch of vectors

```typescript theme={null}
import type { QueryResultItem } from 'cyborgdb';

const response = await index.query({
    queryVectors: [
        [0.1, 0.2, 0.3, 0.4],
        [0.5, 0.6, 0.7, 0.8],
    ],
    topK: 1,
});
const batch = response.results as QueryResultItem[][];

batch.forEach((results, i) => console.log(i, results.map((r) => r.id)));
// Output:
// 0 [ 'doc1' ]
// 1 [ 'doc2' ]
```

#### Float32Array

```typescript theme={null}
import type { QueryResultItem } from 'cyborgdb';

const queries = new Float32Array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]);
const response = await index.query({ queryVectors: queries, dimension: 4, topK: 1 });
const batch = response.results as QueryResultItem[][];

console.log(batch.length);
// Output: 2
```

#### Text, embedded by the service

```typescript theme={null}
import type { QueryResultItem } from 'cyborgdb';

// The index must have been created with embeddingModel
const response = await index.query({
    queryContents: 'machine learning in healthcare',
    topK: 3,
});
console.log((response.results as QueryResultItem[]).map((r) => r.id));
```

#### Hybrid (BM25 + vector)

The index needs at least one full-text field, set with `textFields` or `{ fullText: true }` in [`createIndex()`](../client/create-index#metadata-schema).

```typescript theme={null}
import type { QueryResultItem } from 'cyborgdb';

const response = await index.query({
    queryVectors: [0.1, 0.2, 0.3, 0.4],
    text: 'encrypted search',
    topK: 2,
    alpha: 0.5,
    include: ['metadata'],
});

for (const r of response.results as QueryResultItem[]) {
    console.log(r.id, Number(r.score?.toFixed(4)));
}
// Output:
// doc1 0.0164
// doc2 0.0161
```

#### Filters and search options

```typescript theme={null}
import type { QueryResultItem } from 'cyborgdb';

const response = await index.query({
    queryVectors: [0.1, 0.2, 0.3, 0.4],
    topK: 20,
    nProbes: 5,
    rerankMult: 20,
    greedy: true,
    filters: { category: 'news' },
    include: ['distance', 'metadata'],
});

for (const r of response.results as QueryResultItem[]) {
    console.log(r.id, r.metadata?.category);
}
// Output: doc1 news
```


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