Add configuration for BMad, Claude, OpenCode, and other AI agent tools and workflows.
5.7 KiB
5.7 KiB
Queries Reference
Local API
Find Multiple
const result = await payload.find({
collection: 'posts',
where: {
status: { equals: 'published' },
},
limit: 10,
page: 1,
sort: '-createdAt',
depth: 2,
})
// Result structure
{
docs: Post[],
totalDocs: number,
limit: number,
totalPages: number,
page: number,
pagingCounter: number,
hasPrevPage: boolean,
hasNextPage: boolean,
prevPage: number | null,
nextPage: number | null,
}
Find By ID
const post = await payload.findByID({
collection: 'posts',
id: '123',
depth: 2,
})
Create
const newPost = await payload.create({
collection: 'posts',
data: {
title: 'New Post',
content: '...',
author: userId,
},
user: req.user, // For access control
})
Update
const updated = await payload.update({
collection: 'posts',
id: '123',
data: {
title: 'Updated Title',
},
})
Delete
const deleted = await payload.delete({
collection: 'posts',
id: '123',
})
Query Operators
Comparison
where: {
price: { equals: 100 },
price: { not_equals: 100 },
price: { greater_than: 100 },
price: { greater_than_equal: 100 },
price: { less_than: 100 },
price: { less_than_equal: 100 },
}
String Operations
where: {
title: { like: 'Hello' }, // Case-insensitive contains
title: { contains: 'world' }, // Case-sensitive contains
email: { exists: true }, // Field has value
}
Array Operations
where: {
tags: { in: ['tech', 'design'] }, // Value in array
tags: { not_in: ['spam'] }, // Value not in array
tags: { all: ['featured', 'popular'] }, // Has all values
}
AND/OR Logic
where: {
and: [
{ status: { equals: 'published' } },
{ author: { equals: userId } },
],
}
where: {
or: [
{ status: { equals: 'published' } },
{ author: { equals: userId } },
],
}
// Nested
where: {
and: [
{ status: { equals: 'published' } },
{
or: [
{ featured: { equals: true } },
{ 'author.roles': { in: ['admin'] } },
],
},
],
}
Nested Properties
Query through relationships:
where: {
'author.name': { contains: 'John' },
'category.slug': { equals: 'tech' },
}
Geospatial Queries
where: {
location: {
near: [-73.935242, 40.730610, 10000], // [lng, lat, maxDistanceMeters]
},
}
where: {
location: {
within: {
type: 'Polygon',
coordinates: [[[-74, 40], [-73, 40], [-73, 41], [-74, 41], [-74, 40]]],
},
},
}
Field Selection
Only fetch specific fields:
const posts = await payload.find({
collection: 'posts',
select: {
title: true,
slug: true,
author: true, // Will be populated based on depth
},
})
Depth (Relationship Population)
// depth: 0 - IDs only
{ author: '123' }
// depth: 1 - First level populated
{ author: { id: '123', name: 'John' } }
// depth: 2 (default) - Nested relationships populated
{ author: { id: '123', name: 'John', avatar: { url: '...' } } }
Pagination
// Page-based
await payload.find({
collection: 'posts',
page: 2,
limit: 20,
})
// Cursor-based (more efficient for large datasets)
await payload.find({
collection: 'posts',
where: {
createdAt: { greater_than: lastCursor },
},
limit: 20,
sort: 'createdAt',
})
Sorting
// Single field
sort: 'createdAt' // Ascending
sort: '-createdAt' // Descending
// Multiple fields
sort: ['-featured', '-createdAt']
Access Control in Local API
CRITICAL: Local API bypasses access control by default!
// ❌ INSECURE: Access control bypassed
await payload.find({
collection: 'posts',
user: someUser, // User is ignored!
})
// ✅ SECURE: Access control enforced
await payload.find({
collection: 'posts',
user: someUser,
overrideAccess: false, // REQUIRED
})
REST API
Endpoints
GET /api/{collection} # Find
GET /api/{collection}/{id} # Find by ID
POST /api/{collection} # Create
PATCH /api/{collection}/{id} # Update
DELETE /api/{collection}/{id} # Delete
Query String
GET /api/posts?where[status][equals]=published&limit=10&sort=-createdAt&depth=2
Nested Queries
GET /api/posts?where[author.name][contains]=John
Complex Queries
GET /api/posts?where[or][0][status][equals]=published&where[or][1][author][equals]=123
GraphQL API
Query
query {
Posts(
where: { status: { equals: published } }
limit: 10
sort: "-createdAt"
) {
docs {
id
title
author {
name
}
}
totalDocs
}
}
Mutation
mutation {
createPost(data: { title: "New Post", status: draft }) {
id
title
}
}
Draft Queries
// Published only (default)
await payload.find({ collection: 'posts' })
// Include drafts
await payload.find({
collection: 'posts',
draft: true,
})
Count Only
const count = await payload.count({
collection: 'posts',
where: { status: { equals: 'published' } },
})
// Returns: { totalDocs: number }
Distinct Values
const categories = await payload.find({
collection: 'posts',
select: { category: true },
// Then dedupe in code
})
Performance Tips
- Use indexes - Add
index: trueto frequently queried fields - Limit depth - Lower depth = faster queries
- Select specific fields - Don't fetch what you don't need
- Use pagination - Never fetch all documents
- Avoid nested OR queries - Can be slow on large collections
- Use count for totals - Faster than fetching all docs