stratadb / Collection
Type Alias: Collection<T>
type Collection<T> = object;Defined in: src/collection-types.ts:181
MongoDB-like collection interface for type-safe document operations.
Remarks
Collection provides a complete CRUD API with full type safety. It wraps a SQLite table and provides MongoDB-like methods for querying and manipulating documents.
Key Features:
- Type-safe query filters with auto-completion
- Generated columns for indexed fields (optimized queries)
- JSONB storage for flexible document structure
- Built-in validation using Standard Schema validators
- Batch operations for performance
- Transaction support through database instance
Document Storage:
- All documents stored in a single
dataJSONB column - Indexed fields have generated columns with underscore prefix (e.g.,
_age) - Auto-generated
_idandcreatedAtfields - Optional
updatedAttracking
Comparison to MongoDB:
- Similar API surface for easy migration
- Uses SQLite instead of MongoDB protocol
- Type-safe at compile time (MongoDB client isn't)
- Generated columns optimize common queries
- Standard Schema validation (not MongoDB JSON Schema)
Example
import { StrataDB, createSchema, type Document } from 'stratadb';
import { z } from 'zod';
// Define document type
type User = Document<{
name: string;
email: string;
age: number;
role: 'admin' | 'user';
}>;
// Create schema with validation
const userSchema = createSchema<User>()
.field('name', { type: 'TEXT', indexed: true })
.field('email', { type: 'TEXT', indexed: true, unique: true })
.field('age', { type: 'INTEGER', indexed: true })
.field('role', { type: 'TEXT', indexed: false })
.validator(z.object({
name: z.string().min(1),
email: z.string().email(),
age: z.number().int().min(0),
role: z.enum(['admin', 'user'])
}))
.build();
// Open database and get collection
const db = new StrataDB('myapp.db');
const users = db.collection('users', userSchema);
// Insert documents
const result = await users.insertOne({
name: 'Alice',
email: 'alice@example.com',
age: 30,
role: 'admin'
});
console.log(result._id); // Auto-generated UUID
// Query documents
const admins = await users.find({ role: 'admin' });
const adults = await users.find({ age: { $gte: 18 } });
const alice = await users.findOne({ email: 'alice@example.com' });
// Update documents
await users.updateOne(
{ email: 'alice@example.com' },
{ $set: { role: 'user' } }
);
// Delete documents
await users.deleteMany({ age: { $lt: 18 } });Type Parameters
T
T extends Document
The document type, must extend Document
Properties
name
readonly name: string;Defined in: src/collection-types.ts:185
Collection name (table name in SQLite).
schema
readonly schema: SchemaDefinition<T>;Defined in: src/collection-types.ts:190
Schema definition for this collection.
Methods
count()
count(filter): Promise<number>;Defined in: src/collection-types.ts:329
Count documents matching the query filter.
Parameters
filter
QueryFilter<T>
Query filter to match documents
Returns
Promise<number>
Promise resolving to the count of matching documents
Remarks
More efficient than find(filter).length since it only counts without retrieving document data.
Example
// Count all users
const total = await users.count({});
// Count active admins
const adminCount = await users.count({
role: 'admin',
status: 'active'
});
// Count adults
const adultCount = await users.count({ age: { $gte: 18 } });deleteMany()
deleteMany(filter): Promise<DeleteResult>;Defined in: src/collection-types.ts:752
Delete multiple documents matching the query filter.
Parameters
filter
QueryFilter<T>
Query filter to find documents to delete
Returns
Promise<DeleteResult>
Promise resolving to delete result with statistics
Remarks
Deletes all documents that match the filter. Use an empty filter {} to delete all documents in the collection.
Warning: This operation cannot be undone. Consider backing up data before bulk delete operations.
Example
// Delete all inactive users
const result = await users.deleteMany({ status: 'inactive' });
console.log(`Deleted ${result.deletedCount} users`);
// Delete all documents (use with caution!)
await users.deleteMany({});deleteOne()
deleteOne(filter): Promise<boolean>;Defined in: src/collection-types.ts:501
Delete a single document by ID or filter.
Parameters
filter
Document ID (string) or query filter
string | QueryFilter<T>
Returns
Promise<boolean>
Promise resolving to true if document was deleted, false if not found
Remarks
This method accepts either a string ID or a query filter for maximum flexibility. When you have the document ID, pass it directly as a string for convenience. When you need to delete by other fields, pass a filter object.
Deletes the first document that matches the filter. If no document matches, returns false.
Example
// Delete by ID (string)
const deleted = await users.deleteOne('user-123')
if (deleted) {
console.log('User deleted successfully')
}
// Delete by filter
const deleted = await users.deleteOne({ email: 'inactive@example.com' })
// Delete with complex filter
const deleted = await users.deleteOne({
status: 'inactive',
lastLogin: { $lt: Date.now() - 90 * 24 * 60 * 60 * 1000 } // 90 days
})distinct()
distinct<K>(field, filter?): Promise<T[K][]>;Defined in: src/collection-types.ts:783
Find distinct values for a specified field across the collection.
Type Parameters
K
K extends string | number | symbol
Parameters
field
K
The field name to get distinct values for
filter?
QueryFilter<T>
Optional query filter to narrow results
Returns
Promise<T[K][]>
Promise resolving to array of unique values for the field
Remarks
Returns an array of unique values for the specified field. If a filter is provided, only documents matching the filter are considered.
The method uses SQLite's DISTINCT clause for efficient querying. For indexed fields, uses the generated column; for non-indexed fields, uses JSON extraction.
Example
// Get all unique ages
const ages = await users.distinct('age');
console.log(ages); // [25, 30, 35, 40]
// Get unique roles for active users
const activeRoles = await users.distinct('role', { active: true });
// Get unique tags (array field)
const tags = await users.distinct('tags');drop()
drop(): Promise<void>;Defined in: src/collection-types.ts:835
Drop the collection (delete the table).
Returns
Promise<void>
Promise resolving when the collection is dropped
Remarks
Permanently deletes the collection and all its documents. This operation cannot be undone.
The table and all associated indexes are removed from the database. Use with caution in production environments.
Example
// Drop a temporary collection
await tempCollection.drop();
// Drop with confirmation
if (confirm('Really delete all users?')) {
await users.drop();
}estimatedDocumentCount()
estimatedDocumentCount(): Promise<number>;Defined in: src/collection-types.ts:810
Get an estimated count of documents in the collection.
Returns
Promise<number>
Promise resolving to the estimated document count
Remarks
Returns a fast estimate of the document count using SQLite table statistics. This is much faster than count() for large collections but may not be exact.
Uses SQLite's internal statistics which are updated periodically. For exact counts, use the count() method instead.
Example
const estimate = await users.estimatedDocumentCount();
console.log(`Approximately ${estimate} users`);
// Compare with exact count
const exact = await users.count({});
console.log(`Exact: ${exact}, Estimated: ${estimate}`);find()
find(filter, options?): Promise<readonly T[]>;Defined in: src/collection-types.ts:258
Find all documents matching the query filter.
Parameters
filter
QueryFilter<T>
Query filter to match documents
options?
QueryOptions<T>
Query options for sorting, pagination, and projection
Returns
Promise<readonly T[]>
Promise resolving to array of matching documents
Remarks
Returns all documents that match the filter. For large result sets, use limit and skip options for pagination.
Performance:
- Indexed fields use generated columns (fast)
- Non-indexed fields use jsonb_extract (slower)
- Consider adding indexes for frequently queried fields
Example
// Find all active admins
const admins = await users.find({
role: 'admin',
status: 'active'
});
// Find with sorting and pagination
const page = await users.find(
{ age: { $gte: 18 } },
{ sort: { createdAt: -1 }, limit: 20, skip: 40 }
);
// Find with complex query
const results = await users.find({
$and: [
{ age: { $gte: 18, $lt: 65 } },
{
$or: [
{ role: 'admin' },
{ verified: true }
]
}
]
});findById()
findById(id): Promise<T | null>;Defined in: src/collection-types.ts:212
Find a single document by its ID.
Parameters
id
string
The document ID to search for
Returns
Promise<T | null>
Promise resolving to the document, or null if not found
Remarks
This is the fastest way to retrieve a specific document since it uses the primary key index.
Example
const user = await users.findById('123e4567-e89b-12d3-a456-426614174000');
if (user) {
console.log(user.name);
}findOne()
findOne(filter, options?): Promise<T | null>;Defined in: src/collection-types.ts:299
Find the first document matching the query filter or ID.
Parameters
filter
Document ID or query filter to match documents
string | QueryFilter<T>
options?
Omit<QueryOptions<T>, "limit" | "skip">
Query options for sorting and projection
Returns
Promise<T | null>
Promise resolving to the first matching document, or null if none found
Remarks
Equivalent to find(filter, { ...options, limit: 1 })[0] but more efficient since it stops after finding the first match.
Accepts either a string ID or a full QueryFilter object for flexible querying:
- String ID:
{ _id: string }filter is applied automatically - QueryFilter: Full MongoDB-style query filtering
Example
// Find by document ID
const user = await users.findOne('123e4567-e89b-12d3-a456-426614174000');
if (user) {
console.log(user.name);
}
// Find by query filter
const admin = await users.findOne({ role: 'admin' });
// Find with options
const latest = await users.findOne(
{},
{ sort: { createdAt: -1 } }
);
// Check if email exists
const exists = await users.findOne({ email: 'alice@example.com' });
if (exists) {
console.log('Email already registered');
}findOneAndDelete()
findOneAndDelete(filter, options?): Promise<T | null>;Defined in: src/collection-types.ts:541
Find and delete a single document atomically.
Parameters
filter
Document ID (string) or query filter
string | QueryFilter<T>
options?
Query options (sort)
sort?
SortSpec<T>
Returns
Promise<T | null>
Promise resolving to the deleted document, or null if not found
Remarks
This method accepts either a string ID or a query filter for maximum flexibility. When you have the document ID, pass it directly as a string for convenience. When you need to delete by other fields, pass a filter object.
This operation is atomic - it finds and deletes in a single operation. Useful when you need the deleted document's data (e.g., for logging, undo operations).
When multiple documents match the filter, the sort option determines which one is deleted.
Example
// Delete by ID
const deleted = await users.findOneAndDelete('user-123');
if (deleted) {
console.log(`Deleted user: ${deleted.name}`);
await logDeletion(deleted);
}
// Delete by filter
const deleted = await users.findOneAndDelete({ email: 'old@example.com' });
// Delete with sort (delete oldest inactive user)
const deleted = await users.findOneAndDelete(
{ status: 'inactive' },
{ sort: { createdAt: 1 } }
);findOneAndReplace()
findOneAndReplace(
filter,
replacement,
options?): Promise<T | null>;Defined in: src/collection-types.ts:652
Find and replace a single document atomically.
Parameters
filter
Document ID (string) or query filter
string | QueryFilter<T>
replacement
Omit<T, "_id" | "createdAt" | "updatedAt">
Complete replacement document (without _id, createdAt, updatedAt)
options?
Replace options (sort, returnDocument, upsert)
returnDocument?
"before" | "after"
sort?
SortSpec<T>
upsert?
boolean
Returns
Promise<T | null>
Promise resolving to the document before or after replacement, or null if not found
Remarks
This method accepts either a string ID or a query filter for maximum flexibility. When you have the document ID, pass it directly as a string for convenience. When you need to replace by other fields, pass a filter object.
This operation replaces the ENTIRE document (except _id, createdAt). Unlike findOneAndUpdate which merges fields, this replaces everything. The replacement document is validated against the schema. Default returnDocument is 'after'.
Example
// Replace by ID
const replaced = await users.findOneAndReplace(
'user-123',
{
name: 'New Name',
email: 'new@example.com',
age: 30,
active: true,
tags: []
},
{ returnDocument: 'after' }
);
// Replace by filter
const replaced = await users.findOneAndReplace(
{ email: 'old@example.com' },
{
name: 'New Name',
email: 'new@example.com',
age: 30,
active: true,
tags: []
}
);findOneAndUpdate()
findOneAndUpdate(
filter,
update,
options?): Promise<T | null>;Defined in: src/collection-types.ts:596
Find and update a single document atomically.
Parameters
filter
Document ID (string) or query filter
string | QueryFilter<T>
update
Omit<Partial<T>, "_id" | "createdAt" | "updatedAt">
Partial document with fields to update
options?
Update options (sort, returnDocument, upsert)
returnDocument?
"before" | "after"
sort?
SortSpec<T>
upsert?
boolean
Returns
Promise<T | null>
Promise resolving to the document before or after update, or null if not found
Remarks
This method accepts either a string ID or a query filter for maximum flexibility. When you have the document ID, pass it directly as a string for convenience. When you need to update by other fields, pass a filter object.
This operation is atomic - it finds and updates in a single logical operation. Use returnDocument to control whether you get the document state before or after the update. Default is 'after'.
Example
// Update by ID
const updated = await users.findOneAndUpdate(
'user-123',
{ loginCount: 5 },
{ returnDocument: 'after' }
);
// Update by filter
const updated = await users.findOneAndUpdate(
{ email: 'alice@example.com' },
{ loginCount: 5 },
{ returnDocument: 'after' }
);
console.log(`New login count: ${updated?.loginCount}`);
// Get previous state before update
const before = await users.findOneAndUpdate(
{ _id: userId },
{ status: 'archived' },
{ returnDocument: 'before' }
);
await logStatusChange(before, 'archived');
// Upsert with returnDocument
const result = await users.findOneAndUpdate(
{ email: 'new@example.com' },
{ name: 'New User', age: 25 },
{ upsert: true, returnDocument: 'after' }
);insertMany()
insertMany(docs): Promise<InsertManyResult<T>>;Defined in: src/collection-types.ts:691
Insert multiple documents into the collection.
Parameters
docs
readonly Omit<T, "_id" | "createdAt" | "updatedAt">[]
Array of documents to insert
Returns
Promise<InsertManyResult<T>>
Promise resolving to insert result with all new documents
Remarks
Inserts all documents in a single transaction for performance. If any document fails validation, the entire operation rolls back. Automatically generates id, createdAt, and updatedAt for each document.
Performance: Much faster than multiple insertOne calls since it uses a single transaction.
Throws
If any document fails schema validation
Throws
If any unique constraint is violated
Example
const result = await users.insertMany([
{ name: 'Alice', email: 'alice@example.com', age: 30, role: 'admin' },
{ name: 'Bob', email: 'bob@example.com', age: 25, role: 'user' },
{ name: 'Charlie', email: 'charlie@example.com', age: 35, role: 'user' }
]);
console.log(`Inserted ${result.insertedCount} users`);insertOne()
insertOne(doc): Promise<T>;Defined in: src/collection-types.ts:370
Insert a single document into the collection.
Parameters
doc
Omit<T, "_id" | "createdAt" | "updatedAt">
Document to insert (without _id, createdAt, updatedAt)
Returns
Promise<T>
Promise resolving to the inserted document with generated _id
Remarks
Validates the document against the schema before inserting. Automatically generates:
_id: UUID v4createdAt: Current timestampupdatedAt: Current timestamp (if schema has this field)
Validation: If validation fails, throws ValidationError with details.
Throws
If document fails schema validation
Throws
If unique constraint is violated
Example
try {
const user = await users.insertOne({
name: 'Bob',
email: 'bob@example.com',
age: 25,
role: 'user'
});
console.log(`Inserted user with ID: ${user._id}`);
console.log(`User name: ${user.name}`);
} catch (err) {
if (err instanceof ValidationError) {
console.error('Invalid user:', err.message);
}
}replaceOne()
replaceOne(filter, doc): Promise<T | null>;Defined in: src/collection-types.ts:464
Replace a single document by ID or filter.
Parameters
filter
Document ID (string) or query filter
string | QueryFilter<T>
doc
Omit<T, "_id" | "createdAt" | "updatedAt">
New document to replace with (without _id, createdAt, updatedAt)
Returns
Promise<T | null>
Promise resolving to the replaced document, or null if not found
Remarks
This method accepts either a string ID or a query filter for maximum flexibility. When you have the document ID, pass it directly as a string for convenience. When you need to replace by other fields, pass a filter object.
Completely replaces the matched document with the new document. Preserves _id and createdAt, updates updatedAt. Validates the new document against the schema.
Difference from updateOne:
updateOne: Merges specific fields into existing documentreplaceOne: Replaces entire document (except _id, createdAt)
Throws
If new document fails schema validation
Example
// Replace by ID (string)
const replaced = await users.replaceOne(
'user-123',
{
name: 'Alice Smith',
email: 'alice.smith@example.com',
age: 31,
role: 'admin'
}
);
// Replace by filter
const replaced = await users.replaceOne(
{ email: 'old@example.com' },
{
name: 'Alice Smith',
email: 'new@example.com',
age: 31,
role: 'admin'
}
);updateMany()
updateMany(filter, update): Promise<UpdateResult>;Defined in: src/collection-types.ts:723
Update multiple documents matching the query filter.
Parameters
filter
QueryFilter<T>
Query filter to find documents to update
update
Omit<Partial<T>, "_id" | "createdAt" | "updatedAt">
Update operations to apply
Returns
Promise<UpdateResult>
Promise resolving to update result with statistics
Remarks
Updates all documents that match the filter. Uses MongoDB-style update operators. Automatically updates updatedAt for each modified document.
Example
// Set all inactive users to deleted status
const result = await users.updateMany(
{ status: 'inactive' },
{ $set: { status: 'deleted' } }
);
console.log(`Updated ${result.modifiedCount} users`);
// Give all admins a badge
await users.updateMany(
{ role: 'admin' },
{ $set: { badge: 'admin' } }
);updateOne()
updateOne(
filter,
update,
options?): Promise<T | null>;Defined in: src/collection-types.ts:411
Update a single document matching the query filter or ID.
Parameters
filter
Document ID or query filter to find the document to update
string | QueryFilter<T>
update
Omit<Partial<T>, "_id" | "createdAt" | "updatedAt">
Partial document with fields to update
options?
Optional upsert configuration
upsert?
boolean
Returns
Promise<T | null>
Promise resolving to the updated document, or null if not found
Remarks
Updates the first document that matches the filter. Merges the provided partial document with the existing document. Automatically updates updatedAt if present in schema.
Accepts either a string ID or a full QueryFilter object for flexible targeting:
- String ID:
{ _id: string }filter is applied automatically - QueryFilter: Full MongoDB-style query filtering
Example
// Update by document ID
const updated = await users.updateOne(
'123e4567-e89b-12d3-a456-426614174000',
{ role: 'admin', verified: true }
);
// Update by query filter
await users.updateOne(
{ email: 'alice@example.com' },
{ role: 'admin', verified: true }
);
// Update with upsert
await users.updateOne(
{ email: 'new@example.com' },
{ role: 'user' },
{ upsert: true }
);validate()
validate(doc): Promise<T>;Defined in: src/collection-types.ts:869
Validate a document against the schema (async).
Parameters
doc
unknown
Document to validate
Returns
Promise<T>
Promise resolving to true if valid
Remarks
Validates the document against the schema validator. Supports both synchronous and asynchronous validators. Throws ValidationError if validation fails.
Throws
If document fails validation
Example
try {
await users.validate({
name: 'Alice',
email: 'invalid-email',
age: -5,
role: 'admin'
});
} catch (err) {
if (err instanceof ValidationError) {
console.error(`Invalid field: ${err.field}`);
console.error(`Error: ${err.message}`);
}
}validateSync()
validateSync(doc): T;Defined in: src/collection-types.ts:894
Validate a document against the schema (sync).
Parameters
doc
unknown
Document to validate
Returns
T
True if valid
Remarks
Synchronous version of validate(). Only works with synchronous validators. Throws error if the schema uses async validators.
Throws
If document fails validation
Throws
If schema uses async validators
Example
try {
users.validateSync({ name: 'Alice', email: 'alice@example.com', age: 30, role: 'admin' });
console.log('Document is valid');
} catch (err) {
console.error('Validation failed:', err.message);
}