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

# Types

## Index configuration

These fields of [`client.createIndex()`](./client/create-index) configure the index. There is no `indexConfig` argument and no `IndexIVFFlat` / `IndexIVFPQ` / `IndexIVFSQ` types.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `dimension` | `number` | auto-detect | Vector dimensionality. Taken from the first upsert, or from `embeddingModel`, when omitted. |
| `metric` | `string` | `'euclidean'` | `'euclidean'`, `'squared_euclidean'`, or `'cosine'`. |
| `embeddingModel` | `string` | `undefined` | Name of one of the service's built-in embedding models (listed by `GET /v1/embedding-models`), used for automatic embedding generation. |
| `storagePrecision` | `string` | `'float32'` | `'float32'`, `'float16'`, or TurboQuant `'tq12'`, `'tq8'`, `'tq6'`, `'tq4'`. See [Storage precision](./client/create-index#storage-precision). |
| `metadataSchema` | `{ [field: string]: MetadataFieldPolicy }` | `undefined` | Per-field indexing policy. See [Metadata schema](./client/create-index#metadata-schema). |
| `textFields` | `string[]` | `undefined` | Fields to index for BM25 full-text search. |
| `bm25K1` | `number` | `1.2` | BM25 term-frequency saturation. |
| `bm25B` | `number` | `0.75` | BM25 length normalization. |

### MetadataFieldPolicy

```typescript theme={null}
interface MetadataFieldPolicy {
    filterable?: boolean; // default true
    pattern?: boolean;    // default false
    fullText?: boolean;   // default false
}
```

## Key management

| Parameter | Type | Notes |
| - | - | - |
| `indexKey` | `Uint8Array` | 32-byte key for the SDK-supplied-key path. Pass it again on every `loadIndex()`. The SDK sends it to the service as hex. |
| `kmsName` | `string` | Name of a `kms.registry` entry in the service YAML. The service generates and wraps the key; later calls omit `indexKey`. |

Pass exactly one of the two to `createIndex()`; passing both throws `CyborgDBValidationError`.

## VectorItem

The object shape [`upsert()`](./encrypted-index/upsert) accepts:

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

const item: VectorItem = {
    id: 'unique_identifier',          // Required
    vector: [0.1, 0.2, 0.3, 0.4],     // Optional if the index has an embedding model
    contents: 'text content',         // Optional: string or bytes
    metadata: {                       // Optional
        category: 'research',
        author: 'Dr. Smith',
        tags: ['ai', 'ml'],
        publishedMs: 1768435200000,   // a date, as epoch milliseconds
    },
};
```

## Query result

[`query()`](./encrypted-index/query) resolves to a `QueryResponse` whose `results` is a flat array for one query vector, and an array of arrays for a batch:

```typescript theme={null}
// One query vector: QueryResultItem[]
[
    { id: 'doc1', distance: 0.125, metadata: { category: 'research' } },
    { id: 'doc2', distance: 0.234, metadata: { category: 'news' } },
]

// Batch: QueryResultItem[][], one inner array per query vector
[
    [{ id: 'doc1', distance: 0.125 }, { id: 'doc2', distance: 0.234 }],
    [{ id: 'doc3', distance: 0.156 }, { id: 'doc4', distance: 0.278 }],
]
```

`QueryResultItem` has `id`, and optionally `distance` (vector queries; lower is closer), `score` (hybrid queries, instead of `distance`; higher is more relevant), and `metadata`. `QueryResponse.results` is typed `QueryResultItem[] | QueryResultItem[][]`; narrow it with a cast to the shape your call returns.

## MetadataResult

The item type [`queryMetadata()`](./encrypted-index/query-metadata) resolves to:

```typescript theme={null}
interface MetadataResult {
    id: string;
    score?: number; // Only when text is set
}
```

## BM25Config

Returned by the [`bm25()`](./getters#bm25) getter:

```typescript theme={null}
interface BM25Config {
    k1: number;
    b: number;
    analyzerVersion?: string | null;
}
```

## Field selection

`include` picks the fields returned besides `id`:

| Field | `get()` | `query()` |
| - | - | - |
| `vector` | Yes (default) | Not returned |
| `contents` | Yes (default) | Not returned |
| `metadata` | Yes (default) | Yes |
| `distance` | - | Yes |

`get()` defaults to `['vector', 'contents', 'metadata']`; `query()` defaults to `[]`, which returns only `id`.

## Metadata filtering

`filters` on [`query()`](./encrypted-index/query) and [`queryMetadata()`](./encrypted-index/query-metadata) uses MongoDB-style operators. Nested fields use dot-paths such as `'loc.city'`.

### Operators

| Operator | Meaning | Example |
| - | - | - |
| `$eq` | Equal (also the meaning of a bare value) | `{ category: 'research' }` |
| `$ne` | Not equal | `{ status: { $ne: 'draft' } }` |
| `$gt`, `$gte` | Greater than, or equal | `{ year: { $gte: 2020 } }` |
| `$lt`, `$lte` | Less than, or equal | `{ price: { $lt: 100 } }` |
| `$in` | Value is in the list | `{ tag: { $in: ['ai', 'ml'] } }` |
| `$nin` | Value is not in the list | `{ category: { $nin: ['spam', 'deleted'] } }` |
| `$exists` | Field is present (`true`) or absent (`false`) | `{ reviewer: { $exists: true } }` |
| `$regex` | String matches a regular expression | `{ title: { $regex: '^intro' } }` |
| `$contains` | String contains a substring | `{ title: { $contains: 'guide' } }` |
| `$and` | All sub-filters match | `{ $and: [{ a: 1 }, { b: 2 }] }` |
| `$or` | Any sub-filter matches | `{ $or: [{ x: 1 }, { y: 2 }] }` |
| `$nor` | No sub-filter matches | `{ $nor: [{ status: 'draft' }, { status: 'deleted' }] }` |
| `$not` | The sub-filter doesn't match. Takes one filter object, at the top level. | `{ $not: { price: { $gt: 100 } } }` |

`$gt`, `$gte`, `$lt`, and `$lte` require a number; any other value throws `CyborgDBValidationError`. `$not` can't be nested inside a field (`{ price: { $not: ... } }` is rejected); wrap the whole condition instead. `$regex` and `$contains` resolve from the index only on fields created with `pattern: true`: `query()` falls back to a slower post-filter otherwise, and `queryMetadata()` rejects the filter.

### Examples

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

// Equality
const simpleFilter: FilterExpression = { category: 'research' };

// Range
const rangeFilter: FilterExpression = { published_year: { $gte: 2020, $lte: 2024 } };

// Compound
const complexFilter: FilterExpression = {
    $and: [
        { category: 'research' },
        { confidence: { $gte: 0.9 } },
        { $or: [{ language: 'en' }, { translated: true }] },
    ],
};
```

### Dates

CyborgDB has no date type. Store dates in metadata as integer milliseconds since the Unix epoch (UTC), so range operators work on them. Don't store `Date` objects: the SDK sends them as ISO strings, which only support equality filters.

```typescript theme={null}
const publishedMs = Date.UTC(2026, 0, 15); // 15 January 2026, 00:00 UTC

await index.upsert({
    items: [{ id: 'doc1', vector: [0.1, 0.2, 0.3, 0.4], metadata: { publishedMs } }],
});

// Everything published on or after 2026-01-01
const results = await index.queryMetadata({
    filters: { publishedMs: { $gte: Date.UTC(2026, 0, 1) } },
});
console.log(results);
// Output: [ { id: 'doc1' } ]
```

Values come back as numbers. Convert one back to a `Date` with:

```typescript theme={null}
const [item] = await index.get({ ids: ['doc1'], include: ['metadata'] });
const published = new Date(Number(item.metadata?.publishedMs));
console.log(published.toISOString());
// Output: 2026-01-15T00:00:00.000Z
```

## Distance metrics

| Metric | Description |
| - | - |
| `cosine` | Cosine distance. Suited to normalized embeddings. |
| `euclidean` | Euclidean (L2) distance. |
| `squared_euclidean` | Squared Euclidean distance. Same ranking as `euclidean`, without the square root. |

## Response types

| Type | Fields | Returned by |
| - | - | - |
| `UpsertResponse` | `status: string`, `message?: string` | [`upsert()`](./encrypted-index/upsert) |
| `DeleteResponse` | `status: string`, `message?: string` | [`delete()`](./encrypted-index/delete) |
| `TrainResponse` | `status: string`, `message?: string` | [`train()`](./encrypted-index/train) |
| `HealthResponse` | `status: string`, plus other string fields such as `api_version` and `version` | [`getHealth()`](./client/get-health) |
| `GetResultItem` | `id: string`, `vector?: number[]`, `contents?: string`, `metadata?: VectorMetadata` | [`get()`](./encrypted-index/get) |
| `QueryResponse` | `results: QueryResultItem[] \| QueryResultItem[][]` | [`query()`](./encrypted-index/query) |

Since v0.18, `UpsertResponse` and `DeleteResponse` no longer declare `upsertedCount` / `deletedCount`; those fields were never set. `message` reports how many IDs were sent, not how many existed: deleting an ID that doesn't exist still counts it.

## TypeScript types

### JSON types

```typescript theme={null}
type JsonPrimitive = string | number | boolean | null;
type JsonValue = JsonPrimitive | JsonObject | JsonArray;
interface JsonObject { [key: string]: JsonValue }
type JsonArray = JsonValue[];
type VectorMetadata = JsonObject;
```

### Filter types

```typescript theme={null}
type FilterExpression = { [key: string]: FilterValue | FilterOperator };
type FilterValue = JsonPrimitive | JsonArray;

interface FilterOperator {
    $eq?: FilterValue;
    $ne?: FilterValue;
    $gt?: number;
    $gte?: number;
    $lt?: number;
    $lte?: number;
    $in?: JsonArray;
    $nin?: JsonArray;
    $and?: FilterExpression[];
    $or?: FilterExpression[];
    $nor?: FilterExpression[];
    $not?: FilterExpression;
    $exists?: boolean;
    $regex?: string;
    $contains?: string;
}
```

`FilterOperator` places `$not` inside a field, which the service rejects. A top-level `{ $not: { ... } }` filter works on the service but doesn't match these types; cast it with `as FilterExpression`.

### Request models

The package also exports the generated request and response models `CreateIndexRequest`, `UpsertRequest`, `BatchQueryRequest`, `TrainRequest`, `GetRequest`, `DeleteRequest`, `IndexOperationRequest`, `GetResponseModel`, `ErrorResponseModel`, and `HTTPValidationError`. The SDK methods build these for you; you only need them to call the REST API directly.

## Utility functions

| Function | Description |
| - | - |
| `isJsonValue(value: unknown): value is JsonValue` | Checks for JSON primitives, arrays, and objects. It doesn't reject non-plain objects such as `Date` or `Map`, or `NaN`, and it treats any object that appears twice as circular, even when it isn't. |
| `isError(error: unknown): error is Error` | `true` if `error` is an `Error` instance. |
| `getErrorMessage(error: unknown): string` | `error.message` for an `Error`, otherwise `String(error)`. |

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

const circular: Record<string, unknown> = {};
circular.self = circular;

console.log(isJsonValue({ tags: ['ai', 'ml'], score: 0.9 }), isJsonValue(circular));
// Output: true false
```

`VERSION` is the SDK version string, e.g. `'0.18.0'`.


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