FAQ
Relation Issues
How to update relation fields in cloud functions?
When updating relation fields in cloud functions, you must use the {_id: "xxx"} format.
One-to-One Relation:
// Update user's profile relation
await cloudbase.model('user').doc(userId).update({
profile: { _id: "profile_123" }
});
One-to-Many Relation:
// Update class's student list
await cloudbase.model('class').doc(classId).update({
students: [
{ _id: "student_1" },
{ _id: "student_2" }
]
});
For detailed examples, please refer to Relation Details - Cloud Function Relation Field Operations.
How to work with many-to-many relations?
Many-to-many relations are automatically managed by the system through intermediate tables. You do not need to manually create intermediate tables.
Creating Many-to-Many Relation:
// Student enrolling in courses (many-to-many)
await models.student.create({
data: {
name: "Xiao Ming",
courses: [
{ _id: "course_1" },
{ _id: "course_2" }
]
}
});
Querying Many-to-Many Relation Data:
// Query student and their courses
const { data } = await models.student.get({
filter: { where: { _id: { $eq: "student_123" } } },
select: {
name: true,
courses: {
courseName: true,
credits: true
}
}
});
Intermediate Table Naming Rule: ModelA_ModelB (alphabetical order), for example, the intermediate table for student and course is course_student.
For detailed information, please refer to Relation Details - Many-to-Many Intermediate Table Operations.
Relation field update failed with format error?
This is the most common error, caused by not using the correct format.
Wrong Examples:
// ❌ Wrong: Passing string directly
await models.student.update({
filter: { where: { _id: { $eq: "student_123" } } },
data: { class: "class_456" } // Wrong!
});
// ❌ Wrong: Passing extra fields
await models.student.update({
filter: { where: { _id: { $eq: "student_123" } } },
data: {
class: {
_id: "class_456",
name: "Grade 1 Class 1" // No need to pass other fields
}
}
});
Correct Example:
// ✅ Correct: Using {_id: "xxx"} format
await models.student.update({
filter: { where: { _id: { $eq: "student_123" } } },
data: {
class: { _id: "class_456" }
}
});
For detailed troubleshooting, please refer to Relation Details - Troubleshooting.
Image field upload error exceeds maximum value range?
Image fields store the cloud ID of the image, not the binary content of the image.
Recommended Solution:
Solution 1: Use FileID, URL (Recommended)
// ✅ Recommended: Store image CloudID
{
avatarUrl: "cloud://env-id.xxxx/avatar/user123.jpg"
}
Why is relation query result empty?
Relation query results can be empty for several reasons:
Reason 1: Permission Configuration Issue
Relation model permissions are independent from main model, need to check separately:
- Main model's permission configuration
- Relation model's permission configuration
- Whether current user has permission to access related data
Reason 2: Related Data Actually Does Not Exist
Troubleshooting steps:
- Directly view the relation field value of main record in console
- Check if relation field is empty or contains invalid
_id - Query whether corresponding records exist in relation model
Reason 3: Select Field Configuration Error
Must explicitly specify relation field in select:
// ✅ Correct: Explicitly specify relation field
const { data } = await models.post.get({
filter: { where: { _id: { $eq: "post_123" } } },
select: {
title: true,
comments: { // Must explicitly specify
content: true
}
}
});
Reason 4: Multi-Level Relation Query Not Supported
Relation queries currently only support one level, multi-level nested relations will not return data:
// ❌ Wrong: Multi-level relation not supported
const { data } = await models.post.get({
filter: { where: { _id: { $eq: "post_123" } } },
select: {
title: true,
author: {
name: true,
profile: { // ❌ Second level relation: will not return data
city: true
}
}
}
});
For detailed troubleshooting, please refer to Relation Details - Relation Query Returns Empty.
Why does multi-level relation query not return data?
Relation queries currently only support one level of relation, nested relation queries are not supported.
Unsupported Multi-Level Relation Example:
// ❌ Wrong: Multi-level relation query
select: {
title: true,
author: { // First level relation ✅
name: true,
profile: { // Second level relation ❌ Not supported
address: { // Third level relation ❌ Not supported
city: true
}
}
}
}
Supported One-Level Relation Example:
// ✅ Correct: One-level relation query
select: {
title: true,
author: { // First level relation ✅
name: true,
email: true,
bio: true // Regular field (non-relation field) can be queried normally
}
}
Solutions:
Solution 1: Step-by-Step Query
// Step 1: Query first level relation
const post = await models.post.get({
filter: { where: { _id: { $eq: "post_123" } } },
select: {
title: true,
author: {
_id: true,
name: true,
profileId: true // Get next level relation ID
}
}
});
// Step 2: Query second level relation
if (post.data.author.profileId) {
const profile = await models.profile.get({
filter: { where: { _id: { $eq: post.data.author.profileId } } },
select: {
address: { city: true }
}
});
post.data.author.profile = profile.data;
}
Solution 2: Data Redundancy
// Redundant required fields in first level model
// author model
{
_id: "author_123",
name: "Zhang San",
city: "Beijing", // Redundant field: from profile.address.city
bio: "Personal bio"
}
// This allows retrieving required information in one-level query
const { data } = await models.post.get({
filter: { where: { _id: { $eq: "post_123" } } },
select: {
title: true,
author: {
name: true,
city: true // Query redundant field directly
}
}
});
For detailed information, please refer to Relation Details - Relation Query Level Limitation.
How to configure relation model access permissions?
Relation model permissions are independent from main model, need to be set separately for each model.
Configuration Steps:
- Select the corresponding data model in CloudBase Platform - Data Model
- Click the "Permission Management" tab
- Configure permission rules according to business needs
Common Scenarios:
- Public data: Set to "All users can read"
- Private data: Set to "Only creator can read/write"
- Related data: Ensure relation model permissions allow queries
Example:
// If post model is set to "All users can read"
// But comment model is set to "Only creator can read"
// Then when querying posts, only comments created by current user can be seen
const { data } = await models.post.get({
filter: { where: { _id: { $eq: "post_123" } } },
select: {
title: true,
comments: { // Only returns comments created by current user
content: true
}
}
});
Index Issues
How to choose appropriate index fields?
Choosing index fields should be based on actual query scenarios:
Principle 1: Create indexes for frequently used query conditions
- Analyze the most frequently used query fields in your business
- Create indexes for fields in
whereconditions
Principle 2: Create indexes for sorting fields
- Fields specified in
orderByshould have indexes - Can improve sorting query performance
Principle 3: Order of composite index fields matters
- Put most frequently used query fields first
- Put fields with high selectivity (wide value distribution) first
- For example:
(status, createTime)is better than(createTime, status)(status has limited values)
Principle 4: Avoid too many indexes
- Indexes occupy storage space
- Write operations need to update indexes, affecting performance
- Only create indexes for queries that actually need them
Example:
Assuming there's a student model, common query scenarios:
- Query by age:
where: { age: { $gte: 18 } } - Query by class and age:
where: { classId: "xxx", age: { $gte: 18 } } - Sort by score:
orderBy: { field: 'score', direction: 'desc' }
Recommended Index Configuration:
- Single field index:
age - Composite index:
(classId, age, score)
What is the actual performance impact of indexes?
The impact of indexes on query performance depends on data volume and query complexity:
Performance Difference: With Index vs Without Index:
| Data Volume | Query Time Without Index | Query Time With Index | Performance Improvement |
|---|---|---|---|
| 1,000 records | 10-50 ms | 1-5 ms | 5-10x |
| 10,000 records | 100-500 ms | 5-20 ms | 10-50x |
| 100,000 records | 1-5 seconds | 10-50 ms | 100-500x |
| 1,000,000 records | 10-60 seconds | 20-100 ms | 500-1000x |
Cost of Indexes:
- Storage Space: Each index occupies additional storage space (approximately 10-30% of data size)
- Write Performance: Insert, update, delete operations need to update indexes, affecting write speed (approximately 10-20% increase in time)
Best Practices:
- For read-heavy scenarios: Can create more indexes
- For write-heavy scenarios: Only create necessary indexes
- Regularly analyze query logs to optimize index configuration
Usage Issues
Query conditions correct but result is empty
When using database queries, empty results usually have two situations:
- No data matches the query conditions
- Data is filtered by permission control
Troubleshooting Method
Confirm data existence
- Directly view whether target data exists in collection in CloudBase console
- Check data creation time and field values match expectations
Check permission configuration
- Check if collection's basic permission settings allow current user to read
- Database queries use
_openidfield as data ownership criterion - If using security rules, verify rule expressions are correct
- Confirm query conditions include necessary fields required by security rules
Verify query conditions
- Simplify query conditions, gradually troubleshoot which condition causes empty results
- Check field names, data types, and query syntax are correct
How to handle slow data model queries?
Common causes of slow queries and optimization methods:
Reason 1: Missing Index
Troubleshooting Method:
- Check if fields in query conditions have indexes created
- View data model's index configuration in console
Solution:
- Create indexes for fields in
whereconditions - Create indexes for
orderBysorting fields - Use composite indexes to optimize multi-field queries
Reason 2: Relation Query Level Too Deep
Troubleshooting Method:
- Check if querying multi-level relations (e.g., A → B → C → D)
- View nesting level of relation fields in
select
Solution:
- Reduce relation levels, only query necessary related data
- Use pagination to avoid loading large amounts of related data at once
- Consider data redundancy, redundant commonly used relation fields to main table
Reason 3: Query Data Volume Too Large
Troubleshooting Method:
- Check if using pagination (
pageSizeandpageNo) - View number of records returned in single query
Solution:
- Use pagination, 20-50 records per page
- Use
selectto only query needed fields, avoid querying all fields - Add reasonable
whereconditions to narrow query scope
Example Optimization:
Before optimization (slow):
// ❌ Slow: Query all fields, no pagination, deep relation level
const { data } = await models.post.list({
select: {
title: true,
content: true,
author: {
name: true,
},
comments: { // Relate many comments
content: true,
}
}
});
After optimization (fast):
// ✅ Fast: Only query necessary fields, use pagination, reduce relation level
const { data } = await models.post.list({
filter: {
where: { status: { $eq: 'published' } } // Add filter condition
},
select: {
title: true,
author: { // Only query one level relation
name: true
}
// Query comment data separately, avoid loading all at once
},
pageSize: 20, // Pagination
pageNo: 1
});
How to optimize relation query performance?
Relation query performance optimization recommendations:
Optimization 1: Reduce Relation Levels
// ❌ Avoid: Relation level too deep
select: {
title: true,
author: {
profile: {
address: { // 3 levels of relation
city: true
}
}
}
}
// ✅ Recommended: Maximum 2 levels of relation
select: {
title: true,
author: {
name: true,
city: true // Redundant field
}
}
Optimization 2: Load Related Data On-Demand
// Step 1: Only query main data
const posts = await models.post.list({
select: { title: true, authorId: true }
});
// Step 2: Load detailed information when user clicks
const postDetail = await models.post.get({
filter: { where: { _id: { $eq: postId } } },
select: {
title: true,
content: true,
author: { name: true, avatar: true }
}
});
Optimization 3: Use Data Redundancy
// Redundant commonly used fields in main table, avoid frequent relation queries
{
title: "Article Title",
authorId: "author_123",
authorName: "Zhang San", // Redundant field
authorAvatar: "avatar.jpg" // Redundant field
}
Optimization 4: Batch Query Related Data
// ❌ Avoid: Loop query (N+1 problem)
for (const post of posts) {
const author = await models.user.get({
filter: { where: { _id: { $eq: post.authorId } } }
});
}
// ✅ Recommended: Batch query
const authorIds = posts.map(p => p.authorId);
const authors = await models.user.list({
filter: { where: { _id: { $in: authorIds } } }
});