Skip to main content

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:

  1. Directly view the relation field value of main record in console
  2. Check if relation field is empty or contains invalid _id
  3. 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:

  1. Select the corresponding data model in CloudBase Platform - Data Model
  2. Click the "Permission Management" tab
  3. 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 where conditions

Principle 2: Create indexes for sorting fields

  • Fields specified in orderBy should 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:

  1. Query by age: where: { age: { $gte: 18 } }
  2. Query by class and age: where: { classId: "xxx", age: { $gte: 18 } }
  3. 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 VolumeQuery Time Without IndexQuery Time With IndexPerformance Improvement
1,000 records10-50 ms1-5 ms5-10x
10,000 records100-500 ms5-20 ms10-50x
100,000 records1-5 seconds10-50 ms100-500x
1,000,000 records10-60 seconds20-100 ms500-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:

  1. No data matches the query conditions
  2. Data is filtered by permission control

Troubleshooting Method

  1. Confirm data existence

    • Directly view whether target data exists in collection in CloudBase console
    • Check data creation time and field values match expectations
  2. Check permission configuration

    • Check if collection's basic permission settings allow current user to read
    • Database queries use _openid field as data ownership criterion
    • If using security rules, verify rule expressions are correct
    • Confirm query conditions include necessary fields required by security rules
  3. 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 where conditions
  • Create indexes for orderBy sorting 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 (pageSize and pageNo)
  • View number of records returned in single query

Solution:

  • Use pagination, 20-50 records per page
  • Use select to only query needed fields, avoid querying all fields
  • Add reasonable where conditions 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 } } }
});