Queries
Understanding CRUD operations and basic queries
Queries
Collections provides a powerful query API for performing CRUD operations with full type safety. All operations are automatically typed based on your collection definitions.
Overview
Every collection exposes these operations:
Prop
Type
Read Operations
findMany
Retrieve multiple records with optional filtering and pagination:
// Get all users
const users = await collections.users.findMany()
// With filtering
const activeUsers = await collections.users.findMany({
where: {
status: { equals: 'active' }
}
})
// With pagination
const users = await collections.users.findMany({
limit: 10,
offset: 20
})
// With sorting
const users = await collections.users.findMany({
orderBy: {
createdAt: 'desc'
}
})
// Combined
const users = await collections.users.findMany({
where: {
status: { equals: 'active' }
},
orderBy: {
createdAt: 'desc'
},
limit: 10,
offset: 0
})findUnique
Retrieve a single record by its unique identifier:
const user = await collections.users.findUnique({
where: { id: 1 }
})
// With error handling
try {
const user = await collections.users.findUnique({
where: { id: 1 }
})
console.log(user.name)
} catch (error) {
if (error.code === 'NOT_FOUND') {
console.log('User not found')
}
}findFirst
Retrieve the first record matching criteria:
// Get first active user
const user = await collections.users.findFirst({
where: {
status: { equals: 'active' }
},
orderBy: {
createdAt: 'asc'
}
})
// Get first user with specific email
const user = await collections.users.findFirst({
where: {
email: { equals: 'user@example.com' }
}
})Create Operations
create
Create a single new record:
const user = await collections.users.create({
data: {
name: 'John Doe',
email: 'john@example.com',
status: 'active'
}
})
console.log(user.id) // Auto-generated ID
console.log(user.createdAt) // Auto-generated timestampcreateMany
Create multiple records in a single operation:
const users = await collections.users.createMany({
data: [
{
name: 'John Doe',
email: 'john@example.com'
},
{
name: 'Jane Smith',
email: 'jane@example.com'
},
{
name: 'Bob Johnson',
email: 'bob@example.com'
}
]
})
console.log(users.count) // Number of created recordsUpdate Operations
update
Update a single record:
const user = await collections.users.update({
where: { id: 1 },
data: {
name: 'Jane Doe',
status: 'inactive'
}
})updateMany
Update multiple records matching criteria:
const result = await collections.users.updateMany({
where: {
status: { equals: 'inactive' }
},
data: {
status: 'archived'
}
})
console.log(result.count) // Number of updated recordsDelete Operations
delete
Delete a single record:
await collections.users.delete({
where: { id: 1 }
})deleteMany
Delete multiple records matching criteria:
const result = await collections.users.deleteMany({
where: {
status: { equals: 'archived' }
}
})
console.log(result.count) // Number of deleted recordsCount Operations
count
Count records matching criteria:
// Count all users
const total = await collections.users.count()
// Count active users
const active = await collections.users.count({
where: {
status: { equals: 'active' }
}
})
console.log(`Total: ${total}, Active: ${active}`)Type Safety
All operations are fully typed based on your field definitions:
// Type is inferred from field definitions
const user = await collections.users.create({
data: {
name: 'John Doe', // ✅ string - correct
email: 'john@example.com', // ✅ string - correct
age: 25, // ✅ number - correct
status: 'active' // ✅ 'active' | 'inactive' - enum
}
})
// TypeScript will catch errors
const user = await collections.users.create({
data: {
name: 123, // ❌ Error: number not assignable to string
email: 'invalid', // ❌ Error: invalid email format (validation)
age: '25', // ❌ Error: string not assignable to number
status: 'unknown' // ❌ Error: not in enum
}
})Query Options
All query operations accept these options:
Prop
Type
Return Types
Operations return typed results:
// findMany returns array
const users: User[] = await collections.users.findMany()
// findUnique returns single record or null
const user: User | null = await collections.users.findUnique({
where: { id: 1 }
})
// create returns created record
const newUser: User = await collections.users.create({
data: { name: 'John' }
})
// count returns number
const total: number = await collections.users.count()Error Handling
Operations throw errors for invalid data or database issues:
try {
const user = await collections.users.create({
data: {
name: 'John',
email: 'john@example.com'
}
})
} catch (error) {
if (error.code === 'VALIDATION_ERROR') {
console.log('Validation failed:', error.messages)
} else if (error.code === 'UNIQUE_CONSTRAINT') {
console.log('Email already exists')
} else {
console.log('Database error:', error.message)
}
}See Error Handling for complete error reference.
Examples
User Registration
const registerUser = async (email: string, password: string) => {
// Check if user exists
const existing = await collections.users.findFirst({
where: { email: { equals: email } }
})
if (existing) {
throw new Error('User already exists')
}
// Create user
const user = await collections.users.create({
data: {
email,
password: await hash(password),
status: 'active'
}
})
return user
}Update User Profile
const updateProfile = async (userId: number, updates: Partial<User>) => {
const user = await collections.users.update({
where: { id: userId },
data: updates
})
return user
}Soft Delete
const softDelete = async (userId: number) => {
await collections.users.update({
where: { id: userId },
data: {
deletedAt: new Date(),
status: 'deleted'
}
})
}Next Steps
- Cache Management - Intelligent client-side caching
- Filters - Advanced filtering and operators
- Querying Relations - Loading related data
- Pagination - Pagination and sorting strategies