Collection API
A Collection<T> is returned by db.collection<T>(name). All methods return Promises, even on Node.js where the underlying Rust calls are synchronous.
insert(doc)
Inserts one document and returns its generated _id.
insert(doc: Omit<T, '_id'>): Promise<string>const id = await users.insert({ name: 'Alice', age: 30 })
// id = '01HWZZQ0000000000000000000' (ULID)The _id field in the input is ignored — TalaDB always generates a new ULID.
insertMany(docs)
Inserts multiple documents in a single write transaction and returns an array of generated IDs in insertion order.
insertMany(docs: Omit<T, '_id'>[]): Promise<string[]>const ids = await users.insertMany([
{ name: 'Bob', age: 25 },
{ name: 'Carol', age: 35 },
])find(filter?)
Returns all documents matching the filter. If no filter is provided, returns all documents in the collection.
find(filter?: Filter<T>): Promise<T[]>const all = await users.find()
const young = await users.find({ age: { $lt: 30 } })Documents are returned in ULID insertion order (ascending).
findOne(filter)
Returns the first document matching the filter, or null if no document matches.
findOne(filter: Filter<T>): Promise<T | null>const alice = await users.findOne({ email: 'alice@example.com' })
if (alice) {
console.log(alice.name)
}updateOne(filter, update)
Updates the first document matching the filter. Returns true if a document was found and updated, false if no document matched.
updateOne(filter: Filter<T>, update: Update<T>): Promise<boolean>const updated = await users.updateOne(
{ email: 'alice@example.com' },
{ $set: { age: 31 }, $inc: { loginCount: 1 } },
)updateMany(filter, update)
Updates all documents matching the filter. Returns the number of documents updated.
updateMany(filter: Filter<T>, update: Update<T>): Promise<number>const count = await users.updateMany(
{ role: 'trial' },
{ $set: { role: 'user', upgradedAt: Date.now() } },
)deleteOne(filter)
Deletes the first document matching the filter. Returns true if a document was deleted, false if none matched.
deleteOne(filter: Filter<T>): Promise<boolean>const deleted = await users.deleteOne({ _id: id })deleteMany(filter)
Deletes all documents matching the filter. Returns the number of documents deleted.
deleteMany(filter: Filter<T>): Promise<number>const removed = await users.deleteMany({ active: false })count(filter?)
Returns the number of documents matching the filter. If no filter is provided, returns the total document count.
count(filter?: Filter<T>): Promise<number>const total = await users.count()
const admins = await users.count({ role: 'admin' })createIndex(field)
Creates a secondary B-tree index on a field. The call is idempotent — creating an existing index does nothing.
createIndex(field: keyof Omit<T, '_id'> & string): Promise<void>await users.createIndex('email')
await users.createIndex('age')Index creation backfills all existing documents. For large collections this may be slow — create indexes before inserting bulk data whenever possible.
Full-text search index
Prefix the field name with _fts: to build an inverted token index:
await posts.createIndex('_fts:body')
const results = await posts.find({ body: { $contains: 'rust embedded' } })dropIndex(field)
Removes a secondary index. Queries that relied on the index will fall back to full collection scans.
dropIndex(field: keyof Omit<T, '_id'> & string): Promise<void>await users.dropIndex('age')createVectorIndex(field, options)
Creates a vector index on a numeric-array field. Call once at startup — the operation is idempotent.
createVectorIndex(
field: keyof Omit<T, '_id'> & string,
options: VectorIndexOptions,
): Promise<void>VectorIndexOptions:
| Property | Type | Default | Description |
|---|---|---|---|
dimensions | number | required | Expected length of every stored vector. Enforced on insert and search. |
metric | 'cosine' | 'dot' | 'euclidean' | 'cosine' | Similarity metric used by findNearest. |
// Cosine similarity — best for text embeddings
await articles.createVectorIndex('embedding', { dimensions: 384 })
// Dot product
await articles.createVectorIndex('embedding', { dimensions: 1536, metric: 'dot' })
// Euclidean distance (converted to similarity)
await articles.createVectorIndex('coords', { dimensions: 2, metric: 'euclidean' })Existing documents that already have a valid numeric array in field are backfilled automatically. Documents where field is absent or not a numeric array are skipped silently.
Vectors are stored in a dedicated vec::<collection>::<field> redb table and updated atomically on every insert, updateOne, updateMany, deleteOne, and deleteMany.
Throws IndexExists if a vector index already exists on this field.
dropVectorIndex(field)
Removes a vector index and all its stored vectors. findNearest calls on this field will fail after dropping.
dropVectorIndex(field: keyof Omit<T, '_id'> & string): Promise<void>await articles.dropVectorIndex('embedding')Throws VectorIndexNotFound if no vector index exists on this field.
findNearest(field, vector, topK, filter?)
Returns the topK most similar documents to vector using the named vector index. Results are ordered by descending similarity score (highest first).
findNearest(
field: keyof Omit<T, '_id'> & string,
vector: number[],
topK: number,
filter?: Filter<T>,
): Promise<VectorSearchResult<T>[]>VectorSearchResult<T>:
| Property | Type | Description |
|---|---|---|
document | T | The matched document, including all fields and _id. |
score | number | Similarity score — higher is more similar. Range depends on the metric. |
Score ranges by metric:
| Metric | Range | Notes |
|---|---|---|
cosine | [-1, 1] | 1.0 = identical direction, 0 = orthogonal, -1 = opposite |
dot | Unbounded | Depends on vector magnitude — use with unit-normalised vectors |
euclidean | (0, 1] | 1.0 = identical, approaches 0 as distance increases |
Basic usage:
const query = await embed('how do I reset my password?')
const results = await articles.findNearest('embedding', query, 5)
results.forEach(({ document, score }) => {
console.log(`${score.toFixed(3)} ${document.title}`)
})Hybrid search — metadata filter + vector ranking:
Pass a standard Filter<T> as the fourth argument. Only documents matching the filter are considered as candidates before scoring.
// Find the 5 most relevant english support articles
const results = await articles.findNearest('embedding', query, 5, {
category: 'support',
locale: 'en',
})The filter accepts any operator supported by find — $and, $or, $in, $gt, $exists, etc.
Errors:
VectorIndexNotFound— no vector index exists onfieldVectorDimensionMismatch—vector.lengthdoes not match the index's configureddimensions
watch(filter?)
Returns a WatchHandle that yields fresh snapshots of matching documents after every write to the collection.
watch(filter?: Filter<T>): WatchHandle<T>const handle = users.watch({ role: 'admin' })
// Blocking — waits for next write
const admins = await handle.next()
// Non-blocking — returns null if nothing has changed since last call
const snapshot = await handle.tryNext()
// Async iterator
for await (const snapshot of handle) {
console.log('Admins:', snapshot)
}See Live Queries for full details.
exportSnapshot() / restoreFromSnapshot(bytes)
These are database-level methods, not collection-level. See Snapshot export/import in Features.
const bytes = await db.exportSnapshot() // Uint8Array
const db2 = await openDB('', { snapshot: bytes })