Collections
A collection is a group of documents sharing the same schema. Each collection has typed fields, independent indexes, and configurable options for search, filtering, and sorting.
Create a Collection
POST /collections
Content-Type: application/json
X-TYPESENSE-API-KEY: YOUR_API_KEY
{
"name": "products",
"fields": [
{"name": "title", "type": "string"},
{"name": "description", "type": "string"},
{"name": "price", "type": "float", "sort": true},
{"name": "category", "type": "string", "facet": true},
{"name": "tags", "type": "string[]", "facet": true},
{"name": "in_stock", "type": "bool"},
{"name": "rating", "type": "int32", "sort": true}
],
"default_sorting_field": "price"
}
Field Types
| Type | Description | Filterable | Sortable | Searchable |
|---|---|---|---|---|
string | Full-text searchable text | Yes (exact match) | No | Yes |
string[] | Array of strings | Yes | No | Yes |
int32 | 32-bit signed integer | Yes | Yes | No |
int64 | 64-bit signed integer | Yes | Yes | No |
float | 64-bit floating point | Yes | Yes | No |
bool | Boolean true/false | Yes | No | No |
int32[] | Array of 32-bit integers | Yes | No | No |
int64[] | Array of 64-bit integers | Yes | No | No |
geopoint | Latitude/longitude coordinate | Yes (geo radius) | No * | No |
float[] | Vector embedding (with num_dim) | No | No | Yes (vector) |
* Geopoint fields cannot be used as default_sorting_field or with the sort option, but you can sort by geo distance using the sort_by=location(lat,lng):asc syntax in queries.
Field Options
| Option | Type | Default | Description |
|---|---|---|---|
facet | bool | false | Include this field in facet_by results |
index | bool | true | Index this field for search and filtering |
optional | bool | false | Allow documents without this field |
sort | bool | false | Enable sort_by on this field (numeric and geopoint types) |
stem | bool | true | Apply language stemming to this text field |
locale | string | — | Language override for this field (see Languages for codes) |
num_dim | int | — | Vector dimensions (required for float[] vector fields) |
vec_dist | string | cosine | Vector distance metric: cosine, ip (dot product), l2 (Euclidean) |
Schema Options
| Option | Type | Default | Description |
|---|---|---|---|
default_sorting_field | string | — | Default field for sort_by when not specified in queries |
enable_nested_fields | bool | false | Enable dotted field names for nested objects |
default_language | string | en | Default stemming language (see Languages for codes) |
symbols_to_index | string[] | [] | Special characters to include in the index (e.g., ["+", "#"]) |
token_separators | string[] | [] | Additional characters to split tokens on |
persistence_enabled | bool | true | Persist this collection to disk |
index_mode | string | batch | Ingest mode: batch (rebuild index on commit) or realtime (instant updates) |
Index Modes
Torque has two index modes, set per collection via index_mode in the schema. This is a key architectural difference from Typesense, which always updates documents in place.
| Mode | How It Works | Best For |
|---|---|---|
| Batch (default) | Documents are streamed in, then the full index is rebuilt atomically on commit. The old index serves queries until the new one is ready (zero downtime). | Periodic bulk loads, full refreshes, initial imports, ETL pipelines |
| Realtime | Each upsert or delete is immediately visible via a lightweight overlay. The overlay is merged into the base index during compaction. | Live database sync, continuous streaming, low-latency updates |
Batch Mode
Batch mode is the default and produces the most compact, optimized indexes. The workflow is:
- Client opens a TCP session and sends all documents in batches
- Client sends a Commit message
- Torque rebuilds the entire index in the background (inverted index, filters, sort arrays, HNSW graph)
- The new index is swapped in atomically — queries are never blocked
Create a batch-mode collection (this is the default):
{
"name": "products",
"fields": [
{"name": "title", "type": "string"},
{"name": "price", "type": "float", "sort": true}
]
}
Note: Each commit rebuilds the full index. Batch mode is ideal when you can batch all changes together (e.g., nightly refreshes, periodic syncs). For continuous updates, use realtime mode.
Realtime Mode
Realtime mode makes documents searchable immediately after upsert, without waiting for a full index rebuild. Torque achieves this with an overlay — a lightweight in-memory layer that stores recent mutations and is merged with the base index at query time.
- Client sends an Upsert message — the document is added to the overlay
- Searches merge results from the base index and the overlay transparently
- Compaction periodically consolidates the overlay into a new base index
Create a realtime-mode collection:
{
"name": "products_live",
"index_mode": "realtime",
"fields": [
{"name": "title", "type": "string"},
{"name": "price", "type": "float", "sort": true}
]
}
Overlay & Compaction
The realtime overlay is persisted to disk (via redb) with a sub-second flush interval, so mutations survive restarts. As the overlay grows, search performance may degrade slightly because the overlay is scanned linearly. Compaction rebuilds the base index to absorb the overlay:
- Automatic: Runs on a timer (
--compaction-interval-secs, default 30 min) or when memory pressure exceeds the threshold (--compaction-memory-threshold-percent) - Manual:
POST /collections/{name}/documents/compact - Suspend/Resume: Pause ingestion during maintenance with
POST /collections/{name}/suspendandPOST /collections/{name}/resume
Choosing a Mode
| Batch | Realtime | |
|---|---|---|
| Update visibility | After commit (seconds to minutes) | Immediate (sub-millisecond) |
| Index quality | Fully optimized (best query performance) | Base + overlay (slightly higher latency until compaction) |
| Disk writes | One write per commit | Continuous overlay flush (sub-second interval) |
| Deletes | Remove documents by not including them in the next batch | Instant delete via overlay tombstones |
| Typesense equivalent | No equivalent (Typesense always updates in place) | Similar to Typesense default behavior |
Tip: You can use both modes in the same Torque instance. For example, keep a frequently-updated collection in realtime mode while keeping a large reference dataset in batch mode for optimal query speed.
Nested Fields
Enable nested fields to use dotted field names that map to nested JSON objects:
{
"name": "companies",
"enable_nested_fields": true,
"fields": [
{"name": "name", "type": "string"},
{"name": "address.city", "type": "string", "facet": true},
{"name": "address.country", "type": "string", "facet": true},
{"name": "financials.revenue", "type": "float", "sort": true}
]
}
Documents can then be imported with nested JSON, which Torque automatically flattens to match the field names:
{
"name": "Acme Corp",
"address": {"city": "Stockholm", "country": "Sweden"},
"financials": {"revenue": 1500000.0}
}
Nested fields also support element-level AND filtering. See Filtering for details.
Languages
Torque supports Snowball stemming for 17 languages. Set the language per field using locale or per collection using default_language:
| Code | Language |
|---|---|
en | English (default) |
de | German |
fr | French |
es | Spanish |
pt | Portuguese |
it | Italian |
nl | Dutch |
sv | Swedish |
no | Norwegian |
da | Danish |
fi | Finnish |
ru | Russian |
ar | Arabic |
el | Greek |
hu | Hungarian |
ro | Romanian |
tr | Turkish |
Update Schema
Add or remove fields from an existing collection without deleting it:
PATCH /collections/products
Content-Type: application/json
X-TYPESENSE-API-KEY: YOUR_API_KEY
{
"fields": [
{"name": "brand", "type": "string", "facet": true},
{"name": "old_field", "drop": true}
]
}
Adding a new field builds the index for that field. Setting "drop": true removes the field and its index data.
List Collections
GET /collections
X-TYPESENSE-API-KEY: YOUR_API_KEY
Returns all collections with their schemas, document counts, and creation timestamps.
Get Collection
GET /collections/products
X-TYPESENSE-API-KEY: YOUR_API_KEY
Delete Collection
DELETE /collections/products
X-TYPESENSE-API-KEY: YOUR_API_KEY
Collection Aliases
Aliases are logical names that point to a collection. Use them for zero-downtime schema migrations:
# Create an alias
PUT /aliases/products
Content-Type: application/json
X-TYPESENSE-API-KEY: YOUR_API_KEY
{"collection_name": "products_v2"}
Queries to the alias name are transparently routed to the target collection. To migrate, create a new collection, index your data, then update the alias:
# Switch the alias to the new collection
PUT /aliases/products
{"collection_name": "products_v3"}
# List all aliases
GET /aliases
# Get a specific alias
GET /aliases/products
# Delete an alias
DELETE /aliases/products