Collections
Collections store and query documents. Each collection maps to a SQLite table.
Creating Collections
typescript
import { Strata, createSchema, type Document } from 'stratadb'
type User = Document<{
name: string
email: string
age: number
}>
// Option 1: Separate schema
const userSchema = createSchema<User>()
.field('email', { type: 'TEXT', indexed: true, unique: true })
.field('age', { type: 'INTEGER', indexed: true })
.build()
const db = new Strata({ database: 'app.db' })
const users = db.collection('users', userSchema)
// Option 2: Inline schema
const users = db.collection<User>('users')
.field('email', { type: 'TEXT', indexed: true, unique: true })
.field('age', { type: 'INTEGER', indexed: true })
.build()Insert Operations
typescript
// Insert one - returns the inserted document
const user = await users.insertOne({
name: 'Alice',
email: 'alice@example.com',
age: 30
})
console.log(user._id) // auto-generated UUID
// Insert many - returns { documents, insertedCount }
const result = await users.insertMany([
{ name: 'Bob', email: 'bob@example.com', age: 25 },
{ name: 'Carol', email: 'carol@example.com', age: 35 }
])
console.log(result.insertedCount) // 2Read Operations
typescript
// Find by ID
const user = await users.findById('uuid-here')
// Find one by filter (also accepts string ID)
const admin = await users.findOne({ role: 'admin' })
const user = await users.findOne('uuid-here')
// Find many with options
const results = await users.find(
{ age: { $gte: 18 } },
{ sort: { age: -1 }, limit: 10 }
)
// Count matching documents
const count = await users.count({ status: 'active' })
// Search across multiple fields
const results = await users.search('alice', ['name', 'email'])
const filtered = await users.search('admin', ['role', 'notes'], {
filter: { status: 'active' },
sort: { createdAt: -1 },
limit: 10
})
// Get distinct values for a field
const ages = await users.distinct('age')
const roles = await users.distinct('role', { status: 'active' })
// Fast approximate count (uses SQLite stats)
const approxCount = await users.estimatedDocumentCount()Update Operations
typescript
// Partial update - merges with existing document
const updated = await users.updateOne('uuid-here', { age: 31 })
// Update by filter
await users.updateOne({ email: 'alice@example.com' }, { verified: true })
// Upsert - create if not found
await users.updateOne(
{ email: 'new@example.com' },
{ name: 'New User', age: 25 },
{ upsert: true }
)
// Update many - returns { matchedCount, modifiedCount }
const result = await users.updateMany(
{ status: 'inactive' },
{ status: 'archived' }
)
// Replace entire document (preserves _id and createdAt)
await users.replaceOne('uuid-here', {
name: 'Alice Smith',
email: 'alice.smith@example.com',
age: 31
})Delete Operations
typescript
// Delete one - returns true if deleted
const deleted = await users.deleteOne('uuid-here')
const deleted = await users.deleteOne({ email: 'old@example.com' })
// Delete many - returns { deletedCount }
const result = await users.deleteMany({ status: 'archived' })Atomic Operations
These methods find and modify a document in a single operation, returning the document:
typescript
// Find and delete - returns the deleted document
const deleted = await users.findOneAndDelete({ status: 'expired' })
if (deleted) {
console.log(`Removed user: ${deleted.name}`)
}
// Find and update - returns document before or after update
const updated = await users.findOneAndUpdate(
{ email: 'alice@example.com' },
{ loginCount: 5 },
{ returnDocument: 'after' } // 'before' | 'after' (default: 'after')
)
// Find and replace
const replaced = await users.findOneAndReplace(
{ email: 'old@example.com' },
{ name: 'New Name', email: 'new@example.com', age: 30 },
{ returnDocument: 'after', upsert: true }
)Use atomic operations when you need the document's state, such as for logging, undo functionality, or optimistic concurrency.
Drop Collection
typescript
// Permanently delete the collection and all documents
await users.drop()Error Handling
typescript
import { UniqueConstraintError, ValidationError } from 'stratadb'
try {
await users.insertOne({ email: 'duplicate@example.com' })
} catch (err) {
if (err instanceof UniqueConstraintError) {
console.error(`Duplicate value for ${err.field}`)
}
if (err instanceof ValidationError) {
console.error(`Invalid document: ${err.message}`)
}
}Validation
typescript
// Validate without inserting
try {
const validUser = await users.validate(unknownData)
// validUser is typed as User
} catch (err) {
// ValidationError thrown if invalid
}
// Synchronous validation
const validUser = users.validateSync(unknownData)