db - Database Operations
Complete guide to database CRUD operations, queries, relationships, and semantic data management on the .do platform
The db primitive provides type-safe database operations for the .do platform. It offers a clean, semantic interface for managing data with full support for CRUD operations, complex queries, relationships, and integration with Schema.org types.
Overview
The db primitive is built on Payload CMS and provides a unified API for database operations across all collections. It features:
- Type-Safe CRUD - Create, read, update, and delete operations
- Advanced Queries - Filtering, sorting, pagination, field selection
- Relationships - Query and manage related entities
- Semantic Types - Full integration with
$semantic proxy - Entity Enhancement - Automatic enhancement with predicate methods
- Validation - Collection name validation and security
- RPC Architecture - All operations via RPC to API worker
Type Signatures
interface DB {
list<T>(collection: string, options?: ListOptions): Promise<T[]>
get<T>(collection: string, id: string): Promise<T | null>
create<T>(collection: string, data: Partial<T>, options?: CreateOptions): Promise<T>
update<T>(collection: string, id: string, data: Partial<T>, options?: UpdateOptions): Promise<T>
delete(collection: string, id: string, options?: DeleteOptions): Promise<boolean>
related<T>(entity: { collection: string; id: string }, relationship: PathProxy, targetCollection: string, options?: ListOptions): Promise<T[]>
}Options Types
interface ListOptions {
limit?: number
offset?: number
sort?: string
where?: Record<string, unknown>
include?: string[]
select?: string[]
}
interface CreateOptions {
skipValidation?: boolean
returnFull?: boolean
}
interface UpdateOptions {
skipValidation?: boolean
merge?: boolean
}
interface DeleteOptions {
cascade?: boolean
}Basic CRUD Operations
List Records
Query multiple records from a collection with filtering and pagination.
// List all businesses
db.Businesses.list().then((businesses) => {
console.log(businesses)
})
// List with limit
db.Orders.list({
limit: 10,
}).then((recentOrders) => {
console.log(recentOrders)
})
// List with pagination
db.Orders.list({
limit: 20,
offset: 20,
}).then((page2) => {
console.log(page2)
})
// List with sorting
db.Products.list({
sort: '-rating', // Descending
limit: 10,
}).then((topRated) => {
console.log(topRated)
})
// List with multiple sort fields
db.Orders.list({
sort: '-createdAt,status',
}).then((sorted) => {
console.log(sorted)
})Get Single Record
Retrieve a single record by ID or slug.
// Get by ID
db.Orders.get('ord_abc123').then((order) => {
console.log(order)
})
// Get by slug
db.Businesses.get('acme-inc').then((business) => {
console.log(business)
})
// Handle not found
db.Users.get('usr_xyz').then((maybeUser) => {
if (!maybeUser) {
console.log('User not found')
} else {
console.log('Found user:', maybeUser.name)
}
})
// Get with type inference
interface Order {
id: string
orderNumber: string
total: number
status: string
}
db.Orders.get<Order>('ord_123').then((typedOrder) => {
if (typedOrder) {
console.log(typedOrder.orderNumber) // Type-safe access
}
})Create Records
Create new records with semantic types.
// Simple create
db.People.create({
name: 'Alice Johnson',
email: '[email protected]',
role: 'customer',
}).then((person) => {
console.log('Created person:', person.id)
})
// Create with semantic type
db.Customers.create(
$.Person({
name: 'Bob Smith',
email: '[email protected]',
telephone: '+1-555-0123',
jobTitle: 'Product Manager',
})
).then((customer) => {
console.log('Created customer:', customer.id)
})
// Create with nested data
db.Orders.create({
orderNumber: 'ORD-2024-001',
customer: {
name: 'Charlie Davis',
email: '[email protected]',
},
items: [
{
product: 'Laptop',
quantity: 1,
price: 1299.99,
},
],
total: 1299.99,
status: 'pending',
}).then((order) => {
console.log('Created order:', order.id)
})
// Create with options
db.Products.create(
{
name: 'Smart Widget',
price: 99.99,
},
{
skipValidation: false, // Ensure validation runs
}
).then((validated) => {
console.log('Created product:', validated.id)
})Update Records
Update existing records by ID or slug.
// Simple update
db.Orders.update('ord_123', {
status: 'shipped',
shippedAt: new Date(),
})
// Partial update (merge)
db.Customers.update(
'cus_456',
{
telephone: '+1-555-9999',
},
{
merge: true, // Only update specified fields
}
)
// Replace update
db.Products.update(
'prod_789',
{
name: 'Updated Product',
price: 149.99,
stock: 50,
},
{
merge: false, // Replace entire record
}
)
// Update with semantic type
db.People.update(
'per_123',
$.Person({
jobTitle: 'Senior Engineer',
worksFor: $.Organization({ name: 'New Company' }),
})
)
// Conditional update
db.Orders.get('ord_123').then((order) => {
if (order && order.status === 'pending') {
db.Orders.update('ord_123', {
status: 'processing',
processedAt: new Date(),
})
}
})Delete Records
Delete records by ID or slug.
// Simple delete
db.Orders.delete('ord_123')
// Delete with cascade
db.Customers.delete('cus_456', {
cascade: true, // Also delete related records
})
// Conditional delete
db.Orders.get('ord_789').then((order) => {
if (order && order.status === 'cancelled') {
db.Orders.delete('ord_789')
}
})
// Bulk delete with list + delete
db.Orders.list({
where: {
createdAt: { lt: Date.now() - 365 * 24 * 60 * 60 * 1000 }, // 1 year ago
},
}).then((oldOrders) => {
oldOrders.forEach((order) => {
db.Orders.delete(order.id)
})
})Query Options
Filtering with where
Filter records using MongoDB-style query operators.
// Equality
db.Orders.list({
where: { status: 'active' },
}).then((activeOrders) => {
console.log(activeOrders)
})
// Multiple conditions (AND)
db.Orders.list({
where: {
status: 'active',
createdAt: { gte: Date.now() - 7 * 24 * 60 * 60 * 1000 },
},
}).then((recentActive) => {
console.log(recentActive)
})
// Comparison operators
db.Products.list({
where: {
price: { gte: 100, lte: 500 },
},
}).then((expensive) => {
console.log(expensive)
})
// In operator
db.Orders.list({
where: {
status: { in: ['pending', 'processing', 'shipped'] },
},
}).then((specificStatuses) => {
console.log(specificStatuses)
})
// Not equal
db.Orders.list({
where: {
status: { ne: 'cancelled' },
},
}).then((nonCancelled) => {
console.log(nonCancelled)
})
// Contains (for arrays and strings)
db.Articles.list({
where: {
tags: { contains: 'javascript' },
},
}).then((tagged) => {
console.log(tagged)
})
// Exists check
db.Customers.list({
where: {
telephone: { exists: true },
},
}).then((withPhone) => {
console.log(withPhone)
})Available Operators:
eqor direct value - Equalsne- Not equalsgt- Greater thangte- Greater than or equallt- Less thanlte- Less than or equalin- In arraynin- Not in arraycontains- Contains (string or array)exists- Field exists
Sorting with sort
Sort results by one or more fields.
// Ascending sort
const alphabetical = await db.list('products', {
sort: 'name',
})
// Descending sort (prefix with -)
const newest = await db.list('orders', {
sort: '-createdAt',
})
// Multiple sort fields
const sorted = await db.list('products', {
sort: '-rating,name', // Sort by rating desc, then name asc
})
// Sort with pagination
const topProducts = await db.list('products', {
sort: '-sales',
limit: 20,
offset: 0,
})Pagination with limit and offset
Paginate results efficiently.
// First page
const page1 = await db.list('orders', {
limit: 20,
offset: 0,
})
// Second page
const page2 = await db.list('orders', {
limit: 20,
offset: 20,
})
// Helper function for pagination
async function getPage(collection: string, page: number, pageSize: number) {
return await db.list(collection, {
limit: pageSize,
offset: (page - 1) * pageSize,
})
}
const orders = await getPage('orders', 3, 25) // Page 3, 25 items per pageField Selection with select
Select specific fields to reduce payload size.
// Select specific fields
const names = await db.list('customers', {
select: ['name', 'email'],
})
// Returns: [{ name: '...', email: '...' }, ...]
// Select with ID (always included)
const basic = await db.list('products', {
select: ['name', 'price'],
})
// Returns: [{ id: '...', name: '...', price: ... }, ...]
// Combine with filtering
const activeNames = await db.list('users', {
where: { status: 'active' },
select: ['name', 'email', 'lastLoginAt'],
})Including Relationships with include
Populate related entities in the response.
// Include single relationship
const ordersWithCustomer = await db.list('orders', {
include: ['customer'],
})
// order.customer will be populated object, not just ID
// Include multiple relationships
const fullOrders = await db.list('orders', {
include: ['customer', 'items', 'shippingAddress'],
})
// Include nested relationships
const deepOrders = await db.list('orders', {
include: ['customer', 'customer.company', 'items.product'],
})
// Combine with other options
const recent = await db.list('orders', {
where: { status: 'shipped' },
include: ['customer', 'items'],
sort: '-shippedAt',
limit: 10,
})Relationships
Querying Related Entities
Query entities related through semantic relationships.
// Query related entities
const brands = await db.related({ collection: 'businesses', id: 'biz_123' }, $.owns, 'brands')
// With options
const recentOrders = await db.related({ collection: 'customers', id: 'cus_456' }, $.placed, 'orders', {
where: { status: 'completed' },
sort: '-createdAt',
limit: 10,
})
// Multiple hops
const employees = await db.related({ collection: 'businesses', id: 'biz_789' }, $.employs, 'people')
for (const employee of employees) {
const projects = await db.related({ collection: 'people', id: employee.id }, $.worksOn, 'projects')
console.log(`${employee.name} works on ${projects.length} projects`)
}Creating Relationships
Link entities through semantic predicates.
// Create business
const business = await db.create(
'businesses',
$.Business({
name: 'Tech Innovations Inc',
industry: 'Technology',
})
)
// Create brand
const brand = await db.create(
'brands',
$.Brand({
name: 'InnoTech',
logo: 'https://example.com/logo.png',
})
)
// Link them via relationship
await business.owns(brand) // Using enhanced entity method
// Or manually using related()
const brands = await db.related({ collection: 'businesses', id: business.id }, $.owns, 'brands')Relationship Patterns
Common relationship patterns in business applications.
// One-to-Many: Customer -> Orders
const customer = await db.create(
'customers',
$.Person({
name: 'Alice',
email: '[email protected]',
})
)
const order1 = await db.create('orders', {
customer: { id: customer.id },
total: 99.99,
})
const order2 = await db.create('orders', {
customer: { id: customer.id },
total: 149.99,
})
// Query customer's orders
const customerOrders = await db.list('orders', {
where: { 'customer.id': customer.id },
})
// Many-to-Many: Products <-> Categories
const product = await db.create('products', {
name: 'Laptop',
price: 1299.99,
categories: ['electronics', 'computers'],
})
const electronics = await db.list('products', {
where: { categories: { contains: 'electronics' } },
})
// Hierarchical: Organization -> Departments -> Teams
const org = await db.create('organizations', {
name: 'Acme Corp',
})
const dept = await db.create('departments', {
name: 'Engineering',
organization: { id: org.id },
})
const team = await db.create('teams', {
name: 'Frontend Team',
department: { id: dept.id },
})
// Query hierarchy
const depts = await db.list('departments', {
where: { 'organization.id': org.id },
})
for (const d of depts) {
const teams = await db.list('teams', {
where: { 'department.id': d.id },
})
console.log(`${d.name}: ${teams.length} teams`)
}Integration with $ Semantic Proxy
Creating Records with Semantic Types
Use Schema.org types for rich, semantic data.
// Create Person with semantic type
const person = await db.create(
'people',
$.Person({
name: 'John Doe',
givenName: 'John',
familyName: 'Doe',
email: '[email protected]',
jobTitle: 'Software Engineer',
worksFor: $.Organization({
name: 'Tech Corp',
}),
})
)
// Create Product with semantic type
const product = await db.create(
'products',
$.Product({
name: 'Smart Widget Pro',
description: 'Advanced smart widget with AI',
sku: 'SWP-001',
brand: $.Brand({ name: 'WidgetCo' }),
offers: $.Offer({
price: 299.99,
priceCurrency: 'USD',
availability: 'https://schema.org/InStock',
}),
})
)
// Create Event with semantic type
const event = await db.create(
'events',
$.Event({
name: 'Tech Conference 2024',
startDate: '2024-06-15T09:00:00Z',
endDate: '2024-06-17T18:00:00Z',
location: $.Place({
name: 'Convention Center',
address: {
addressLocality: 'San Francisco',
addressRegion: 'CA',
},
}),
organizer: $.Organization({ name: 'Tech Events Inc' }),
})
)Querying with Semantic Filters
Filter using Schema.org properties.
// Find all Software Engineers
const engineers = await db.list('people', {
where: {
jobTitle: 'Software Engineer',
},
})
// Find in-stock products
const available = await db.list('products', {
where: {
'offers.availability': 'https://schema.org/InStock',
},
})
// Find events in specific location
const sfEvents = await db.list('events', {
where: {
'location.address.addressLocality': 'San Francisco',
},
})Advanced Query Patterns
Complex Filtering
Combine multiple conditions and operators.
// Date range with status
const recentActiveOrders = await db.list('orders', {
where: {
status: { in: ['pending', 'processing'] },
createdAt: {
gte: Date.now() - 30 * 24 * 60 * 60 * 1000, // 30 days ago
lte: Date.now(),
},
total: { gte: 100 },
},
})
// Text search with filters
const searchResults = await db.list('products', {
where: {
name: { contains: 'laptop' },
price: { lte: 2000 },
'offers.availability': 'https://schema.org/InStock',
},
sort: '-rating',
limit: 20,
})
// Complex nested conditions
const qualified = await db.list('customers', {
where: {
'stats.totalOrders': { gte: 5 },
'stats.totalSpent': { gte: 1000 },
status: 'active',
'preferences.marketing': true,
},
})Aggregation Patterns
While db doesn't have explicit aggregation, you can aggregate in code:
// Calculate total revenue
const orders = await db.list('orders', {
where: { status: 'completed' },
select: ['total'],
})
const totalRevenue = orders.reduce((sum, order) => sum + order.total, 0)
// Group by status
const allOrders = await db.list('orders', {
select: ['status'],
})
const byStatus = allOrders.reduce(
(acc, order) => {
acc[order.status] = (acc[order.status] || 0) + 1
return acc
},
{} as Record<string, number>
)
// Average rating
const products = await db.list('products', {
select: ['rating'],
})
const avgRating = products.reduce((sum, p) => sum + (p.rating || 0), 0) / products.lengthBatch Operations
Process multiple records efficiently.
// Batch create
const newProducts = [
{ name: 'Product 1', price: 10 },
{ name: 'Product 2', price: 20 },
{ name: 'Product 3', price: 30 },
]
const created = await Promise.all(newProducts.map((p) => db.create('products', p)))
// Batch update
const pendingOrders = await db.list('orders', {
where: { status: 'pending' },
})
await Promise.all(pendingOrders.map((order) => db.update('orders', order.id, { status: 'processing' })))
// Batch delete
const oldOrders = await db.list('orders', {
where: {
status: 'completed',
completedAt: { lt: Date.now() - 365 * 24 * 60 * 60 * 1000 },
},
})
await Promise.all(oldOrders.map((order) => db.delete('orders', order.id)))Complete Application Examples
E-Commerce Order System
Full order processing workflow.
// Create customer
const customer = await db.create(
'customers',
$.Person({
name: 'Emily Johnson',
email: '[email protected]',
telephone: '+1-555-0200',
address: $.PostalAddress({
streetAddress: '456 Oak Street',
addressLocality: 'Portland',
addressRegion: 'OR',
postalCode: '97201',
}),
})
)
// Browse products
const products = await db.list('products', {
where: {
'offers.availability': 'https://schema.org/InStock',
price: { lte: 500 },
},
sort: '-rating',
limit: 20,
})
// Add to cart
const cartItems = []
for (const product of products.slice(0, 2)) {
cartItems.push({
product: { id: product.id },
quantity: 1,
price: product.price,
})
}
// Create order
const order = await db.create(
'orders',
$.Order({
orderNumber: `ORD-${Date.now()}`,
orderDate: new Date(),
customer: { id: customer.id },
orderedItem: cartItems,
totalPrice: cartItems.reduce((sum, item) => sum + item.price, 0),
priceCurrency: 'USD',
orderStatus: 'https://schema.org/OrderProcessing',
})
)
// Process payment
const payment = await db.create('payments', {
order: { id: order.id },
amount: order.totalPrice,
currency: order.priceCurrency,
status: 'pending',
})
// Update order status
await db.update('orders', order.id, {
orderStatus: 'https://schema.org/OrderPaymentDue',
payment: { id: payment.id },
})
// Query customer's order history
const customerOrders = await db.list('orders', {
where: { 'customer.id': customer.id },
sort: '-orderDate',
include: ['orderedItem'],
})CRM Contact Management
Customer relationship tracking.
// Create contact
const contact = await db.create(
'contacts',
$.Person({
name: 'Sarah Williams',
email: '[email protected]',
telephone: '+1-555-0300',
jobTitle: 'VP of Sales',
worksFor: $.Organization({
name: 'BigCorp Inc',
industry: 'Manufacturing',
}),
})
)
// Log interaction
const interaction = await db.create('interactions', {
contact: { id: contact.id },
type: 'call',
notes: 'Discussed product demo',
date: new Date(),
outcome: 'interested',
})
// Create opportunity
const opportunity = await db.create('opportunities', {
name: 'BigCorp - Q1 Deal',
contact: { id: contact.id },
amount: 50000,
stage: 'Qualification',
closeDate: '2024-03-31',
probability: 0.5,
})
// Track activities
const activities = await db.list('interactions', {
where: { 'contact.id': contact.id },
sort: '-date',
limit: 10,
})
// Update opportunity stage
await db.update('opportunities', opportunity.id, {
stage: 'Proposal',
probability: 0.7,
})
// Find hot opportunities
const hotOpps = await db.list('opportunities', {
where: {
stage: { in: ['Proposal', 'Negotiation'] },
amount: { gte: 10000 },
closeDate: { lte: Date.now() + 30 * 24 * 60 * 60 * 1000 },
},
sort: '-amount',
include: ['contact'],
})Content Management System
Blog and content workflow.
// Create author
const author = await db.create(
'authors',
$.Person({
name: 'Tech Blogger',
email: '[email protected]',
url: 'https://techblog.example.com/author/tech-blogger',
})
)
// Create article draft
const article = await db.create(
'articles',
$.Article({
headline: 'Getting Started with Semantic Web',
description: 'Learn the basics of semantic web technologies',
articleBody: 'Full article content here...',
author: { id: author.id },
dateCreated: new Date(),
articleSection: 'Tutorial',
keywords: ['semantic-web', 'rdf', 'linked-data'],
status: 'draft',
})
)
// Add images
const image = await db.create('media', {
article: { id: article.id },
url: 'https://example.com/article-image.jpg',
caption: 'Semantic web diagram',
type: 'image',
})
// Update article with image
await db.update('articles', article.id, {
image: image.url,
})
// Publish article
await db.update('articles', article.id, {
status: 'published',
datePublished: new Date(),
})
// Query published articles
const recentArticles = await db.list('articles', {
where: { status: 'published' },
sort: '-datePublished',
limit: 10,
include: ['author'],
})
// Get articles by category
const tutorials = await db.list('articles', {
where: {
articleSection: 'Tutorial',
status: 'published',
},
sort: '-datePublished',
})
// Search articles
const searchResults = await db.list('articles', {
where: {
headline: { contains: 'semantic' },
status: 'published',
},
})Inventory Management
Track products and stock levels.
// Create warehouse
const warehouse = await db.create(
'warehouses',
$.Place({
name: 'Main Warehouse',
address: {
streetAddress: '123 Storage Lane',
addressLocality: 'Seattle',
addressRegion: 'WA',
postalCode: '98101',
},
})
)
// Add products with inventory
const product = await db.create(
'products',
$.Product({
name: 'Widget Pro',
sku: 'WGT-PRO-001',
price: 49.99,
inventory: {
warehouse: { id: warehouse.id },
quantity: 100,
reorderPoint: 20,
},
})
)
// Record sale (decrease inventory)
const order = await db.create('orders', {
product: { id: product.id },
quantity: 5,
})
// Update inventory
const currentProduct = await db.get('products', product.id)
await db.update('products', product.id, {
'inventory.quantity': currentProduct.inventory.quantity - 5,
})
// Check low stock
const lowStock = await db.list('products', {
where: {
'inventory.quantity': { lte: 20 },
},
})
// Generate reorder report
for (const item of lowStock) {
console.log(`Reorder needed: ${item.name} (${item.inventory.quantity} remaining)`)
}
// Record restocking
const restock = await db.create('restocks', {
product: { id: product.id },
warehouse: { id: warehouse.id },
quantity: 50,
date: new Date(),
})
await db.update('products', product.id, {
'inventory.quantity': currentProduct.inventory.quantity + 50,
})Transaction Patterns
While db doesn't have explicit transactions, you can implement transaction-like patterns:
// Rollback pattern
async function transferInventory(fromWarehouse: string, toWarehouse: string, productId: string, quantity: number) {
// Get current state
const product = await db.get('products', productId)
const fromInv = product.inventory.find((i) => i.warehouse.id === fromWarehouse)
const toInv = product.inventory.find((i) => i.warehouse.id === toWarehouse)
if (!fromInv || fromInv.quantity < quantity) {
throw new Error('Insufficient inventory')
}
try {
// Decrease from source
await db.update('products', productId, {
inventory: product.inventory.map((i) => (i.warehouse.id === fromWarehouse ? { ...i, quantity: i.quantity - quantity } : i)),
})
// Increase at destination
await db.update('products', productId, {
inventory: product.inventory.map((i) => (i.warehouse.id === toWarehouse ? { ...i, quantity: i.quantity + quantity } : i)),
})
// Log transfer
await db.create('transfers', {
product: { id: productId },
fromWarehouse: { id: fromWarehouse },
toWarehouse: { id: toWarehouse },
quantity,
date: new Date(),
})
} catch (error) {
// Rollback: restore original state
await db.update('products', productId, {
inventory: product.inventory,
})
throw error
}
}Performance Considerations
1. Use Filters Instead of Loading All Records
// ❌ Bad: Load all, filter in code
const allOrders = await db.list('orders')
const pending = allOrders.filter((o) => o.status === 'pending')
// ✅ Good: Filter at database level
const pending = await db.list('orders', {
where: { status: 'pending' },
})2. Select Only Needed Fields
// ❌ Bad: Load all fields
const orders = await db.list('orders')
// ✅ Good: Select specific fields
const orders = await db.list('orders', {
select: ['orderNumber', 'status', 'total'],
})3. Use Pagination for Large Datasets
// ❌ Bad: Load everything
const allProducts = await db.list('products')
// ✅ Good: Paginate
async function* paginateProducts(pageSize = 100) {
let offset = 0
while (true) {
const page = await db.list('products', {
limit: pageSize,
offset,
})
if (page.length === 0) break
yield page
offset += pageSize
}
}
for await (const page of paginateProducts()) {
// Process page
}4. Batch Operations with Promise.all
// ❌ Bad: Sequential updates
for (const order of orders) {
await db.update('orders', order.id, { status: 'shipped' })
}
// ✅ Good: Parallel updates
await Promise.all(orders.map((order) => db.update('orders', order.id, { status: 'shipped' })))5. Cache Frequently Accessed Data
// Simple in-memory cache
const cache = new Map()
async function getCachedProduct(id: string) {
if (cache.has(id)) {
return cache.get(id)
}
const product = await db.get('products', id)
cache.set(id, product)
return product
}Common Pitfalls and Solutions
1. Forgetting to Handle Null Returns
// ❌ Bad: Assumes record exists
const order = await db.get('orders', 'ord_123')
console.log(order.total) // May throw if order is null
// ✅ Good: Check for null
const order = await db.get('orders', 'ord_123')
if (order) {
console.log(order.total)
} else {
console.log('Order not found')
}2. Invalid Collection Names
// ❌ Bad: Invalid characters
await db.list('../../../secret-data') // Throws validation error
// ✅ Good: Valid collection name
await db.list('orders')3. Incorrect Query Operators
// ❌ Bad: Wrong operator syntax
await db.list('orders', {
where: { total: { greater_than: 100 } }, // Invalid operator
})
// ✅ Good: Correct operator
await db.list('orders', {
where: { total: { gt: 100 } },
})4. Forgetting to Await
// ❌ Bad: Missing await
const orders = db.list('orders') // Returns Promise, not data
// ✅ Good: With await
const orders = await db.list('orders')Readonly vs Authenticated Mode
Readonly Mode (Anonymous)
Anonymous users can only read data:
// ✅ Available: List and get
const orders = await db.list('orders')
const order = await db.get('orders', 'ord_123')
// ❌ Blocked: Write operations
await db.create('orders', { ... }) // Error: Authentication required
await db.update('orders', id, { ... }) // Error: Authentication required
await db.delete('orders', id) // Error: Authentication requiredAuthenticated Mode
All operations available with proper authentication:
// All CRUD operations
await db.create('orders', { ... })
await db.update('orders', id, { ... })
await db.delete('orders', id)
// Check authentication
const currentUser = user.current()
if (currentUser) {
// Full access
await db.create('orders', { ... })
}Related Primitives
$- Semantic proxy for creating typed objectson- Event handlers triggered by database changessend- Publish events on database operationsuser- Check permissions before database operations
Next Steps
- Semantic Types with $ - Create rich semantic data
- Event-Driven Patterns - React to database changes
- Examples - Real-world database patterns
- Payload CMS Docs - Underlying database system
$ - Semantic Context Proxy
Complete guide to the $ semantic proxy for creating Schema.org types and event patterns in the .do platform
ai - AI Operations
Complete guide to AI operations in MCP.do - text generation, structured output, embeddings, and batch processing with support for multiple models including GPT-5, Claude Sonnet 4.5, Llama 4, Grok 4, and Gemini 2.5 Pro