Tìm bản ghi
Tìm bản ghi Truy vấn bản ghi từ bảng với lọc, sắp xếp, phân trang và chọn trường. Cách dùng cơ bản // Find all records (up to default limit of 10) const result = await $ctx.$repos.products.find({}); // Access the data const products = result.data; // Array of product records Tham
Tìm bản ghi
Truy vấn bản ghi từ bảng với lọc, sắp xếp, phân trang và chọn trường.
Cách dùng cơ bản
// Find all records (up to default limit of 10)
const result = await $ctx.$repos.products.find({});
// Access the data
const products = result.data; // Array of product records
Tham số
await $ctx.$repos.tableName.find({
filter: { ... }, // Filter conditions (optional)
fields: '...', // Fields to return (optional)
limit: 10, // Max records to return (optional, default: 10)
sort: '...', // Sort order (optional, default: primary key field)
meta: 'totalCount' // Request metadata (optional)
})
Tìm bản ghi
Get all records (no limit)
const result = await $ctx.$repos.products.find({
limit: 0 // 0 = no limit, fetch all records
});
const allProducts = result.data;
Get limited records
const result = await $ctx.$repos.products.find({
limit: 20 // Return max 20 records
});
Filter records
const result = await $ctx.$repos.products.find({
filter: {
category: { _eq: 'electronics' },
price: { _gte: 100 }
}
});
Lọc với nhiều điều kiện
const result = await $ctx.$repos.products.find({
filter: {
_and: [
{ category: { _eq: 'electronics' } },
{ price: { _between: [100, 500] } },
{ isActive: { _eq: true } }
]
}
});
Chọn trường
Trả về các trường xác định
const result = await $ctx.$repos.products.find({
fields: 'id,name,price' // Comma-separated field names
});
Trả về mọi trường (mặc định)
const result = await $ctx.$repos.products.find({
// No fields parameter = return all fields
});
Gồm trường của bảng liên quan
const result = await $ctx.$repos.products.find({
fields: 'id,name,category.name,category.description'
});
// Returns: [{id: 1, name: "Phone", category: {name: "Electronics", description: "..."}}]
Gồm mọi trường từ một quan hệ
const result = await $ctx.$repos.products.find({
fields: 'id,name,category.*' // category.* = all category fields
});
Loại trừ trường
const result = await $ctx.$repos.enfyra_route_handler.find({
fields: '-compiledCode'
});
Trường có tiền tố - sẽ chuyển phạm vi fields sang chế độ loại trừ. Ở chế độ này, tên trường dương bị bỏ qua; vì vậy fields: 'id,-compiledCode' trả về mọi trường có thể đọc trừ compiledCode.
Loại trừ lồng nhau dùng ký pháp dấu chấm:
const result = await $ctx.$repos.posts.find({
fields: '-author.avatar'
});
Truy vấn deep (quan hệ lồng nhau)
Với truy vấn lồng nhau phức tạp qua nhiều cấp, hãy dùng tham số deep:
// Fetch products with category, and category's parent category
const result = await $ctx.$repos.products.find({
fields: 'id,name',
deep: {
category: {
fields: 'id,name',
deep: {
parent: {
fields: 'id,name'
}
}
}
}
});
// With filter, sort, and pagination
const result = await $ctx.$repos.products.find({
fields: 'id,name',
deep: {
category: {
fields: 'id,name',
filter: { isActive: { _eq: true } },
sort: 'name',
limit: 10
}
}
});
Trường deep cũng hỗ trợ chế độ loại trừ ở từng phạm vi lồng nhau:
const result = await $ctx.$repos.posts.find({
fields: 'id,title',
deep: {
comments: {
fields: '-compiledCode,-author.avatar',
limit: 10,
deep: {
author: {
fields: '-avatar'
}
}
}
}
});
Để xem hướng dẫn đầy đủ về deep query, hãy đọc Hướng dẫn Deep Queries, bao gồm: - Ví dụ lồng relation nhiều cấp - Lọc relation lồng nhau - Sắp xếp và phân trang theo từng cấp - Thực hành tốt về hiệu năng - URL query examples
Aggregate kết quả tính toán
Dùng aggregate() khi cần các giá trị đã tính toán thay vì raw record. Đây là phương thức riêng, không phải option của find(). Kết quả nằm trong data, không trả raw record và không dùng meta.aggregate.
Summary đơn giản
Bỏ qua dimensions để nhận một summary row cho tập dữ liệu sau filter:
const result = await $ctx.$repos.orders.aggregate({
filter: {
status: { _eq: 'paid' }
},
measures: {
orders: { count: 'id' },
revenue: { sum: 'amount' },
averageOrderValue: { avg: 'amount' }
}
});
// result.data[0] = { orders: 42, revenue: 18400, averageOrderValue: 438.1 }
Các operation được hỗ trợ là count, countDistinct, sum, avg, min và max. Các operation tính trên số yêu cầu field dạng số. Dùng countDistinct để đếm giá trị duy nhất, chẳng hạn số khách hàng.
Grouped analytics
Thêm dimensions khi cần một row cho từng giá trị hoặc time bucket:
const result = await $ctx.$repos.ai_usage.aggregate({
filter: {
createdAt: {
_gte: '2026-08-01T00:00:00+07:00',
_lte: '2026-08-31T23:59:59.999+07:00'
}
},
dimensions: [
{
field: 'createdAt',
bucket: 'day',
timezone: 'Asia/Ho_Chi_Minh'
}
],
measures: {
requests: { count: 'id' },
totalTokens: { sum: 'totalTokens' },
creditChargedMilli: { sum: 'creditChargedMilli' }
},
sort: [{ field: 'createdAt', direction: 'asc' }],
limit: 100
});
Dimension có thể là scalar field hoặc date bucket với hour, day, week, month hay year. Field trong sort phải trỏ tới output key của dimension hoặc tên measure. Dùng page và limit để phân trang các grouped row.
Các field dùng trong aggregate vẫn chịu kiểm tra authorization và giới hạn với field được mã hóa như các repository query khác. Khi query đi qua ranh giới bảo mật của user, hãy dùng repository có enforcement quyền trường như $ctx.$repos.main hoặc $ctx.$repos.secure.<tableName>.
Không đặt aggregate bên trong find(); dạng cũ này không còn được hỗ trợ.
Sắp xếp
Sort ascending
const result = await $ctx.$repos.products.find({
sort: 'name' // Sort by name ascending
});
Sort descending
const result = await $ctx.$repos.products.find({
sort: '-price' // Prefix with "-" for descending
});
Multi-field sorting
const result = await $ctx.$repos.products.find({
sort: 'category,-price' // Sort by category ASC, then price DESC
});
Toán tử lọc
Tham số filter hỗ trợ các toán tử tương tự MongoDB:
Toán tử so sánh
filter: {
price: { _eq: 100 }, // Equal to
price: { _neq: 100 }, // Not equal to
price: { _gt: 100 }, // Greater than
price: { _gte: 100 }, // Greater than or equal
price: { _lt: 500 }, // Less than
price: { _lte: 500 }, // Less than or equal
price: { _between: [100, 500] } // Between (inclusive)
}
Array Operators
filter: {
category: { _in: ['electronics', 'gadgets'] }, // In array
category: { _not_in: ['discontinued', 'old'] } // Not in array
}
Text Search Operators
filter: {
name: { _contains: 'phone' }, // Contains text (case-insensitive)
name: { _starts_with: 'Apple' }, // Starts with
name: { _ends_with: 'Pro' } // Ends with
}
Null Checks
filter: {
description: { _is_null: true }, // Field is null
description: { _is_not_null: true } // Field is not null
}
Logical Operators
filter: {
_and: [ // All conditions must match
{ category: { _eq: 'electronics' } },
{ price: { _gte: 100 } }
],
_or: [ // At least one condition must match
{ status: { _eq: 'active' } },
{ status: { _eq: 'pending' } }
],
_not: { // Negate condition
category: { _eq: 'discontinued' }
}
}
Complex Combinations
filter: {
_and: [
{ category: { _in: ['electronics', 'gadgets'] } },
{
_or: [
{ price: { _lt: 100 } },
{ isOnSale: { _eq: true } }
]
},
{ description: { _is_not_null: true } }
]
}
Lọc theo relation
Lọc bản ghi theo dữ liệu của bảng liên quan:
// Find products where category name is 'Electronics'
const result = await $ctx.$repos.products.find({
filter: {
category: {
name: { _eq: 'Electronics' }
}
}
});
Metadata của truy vấn
Yêu cầu metadata cho truy vấn:
const result = await $ctx.$repos.products.find({
filter: { category: { _eq: 'electronics' } },
meta: 'totalCount' // Get total count of all records (before filter)
});
console.log(result.meta.totalCount); // Total records in table
console.log(result.data.length); // Records matching filter
Các tùy chọn metadata có sẵn:
- 'totalCount' - Total number of records in table (ignores filter)
- 'filterCount' - Number of records matching the filter
- ['totalCount', 'filterCount'] - Both counts
Ví dụ hoàn chỉnh
const result = await $ctx.$repos.products.find({
filter: {
_and: [
{ category: { _in: ['electronics', 'gadgets'] } },
{ price: { _between: [100, 500] } },
{ isActive: { _eq: true } },
{ description: { _is_not_null: true } }
]
},
fields: 'id,name,price,category.name',
sort: '-price',
limit: 20,
meta: ['totalCount', 'filterCount']
});
const products = result.data;
const totalCount = result.meta.totalCount;
const filteredCount = result.meta.filterCount;
Tiếp theo
- Xem Tạo, cập nhật và xóa bản ghi
- Tìm hiểu Mẫu phổ biến
- Xem Lọc truy vấn để biết thêm ví dụ lọc