Working with Document Databases in Cloud Functions
CloudBase document database is a flexible, scalable NoSQL database that supports JSON document storage. In cloud functions, you can operate the database using the Node.js SDK or HTTP API, enabling data CRUD operations, aggregation queries, and other features.
Database Overview
Core Concepts
- (Collection): Similar to a table in a relational database, used for storing documents.
- (Document): The basic storage unit in a database, using JSON format.
- (Data Model): Structured data definition, providing type safety and data validation
- (Index): A data structure that improves query performance
Technical Advantages
- Flexibility: No need to predefine table schema, supports dynamic fields
- Scalability: Automatically scale, supports massive data storage
- Consistency: Supports ACID transactions, ensures data consistency
- Real-time: Supports real-time data monitoring and synchronization
Overview of Operation Methods
📄️ Collection Operations
Directly operate database collections with a flexible NoSQL operation method
📄️ Data Model Operations
Using a structured data model to provide type safety and data validation
📄️ Advanced Features
Advanced features such as transaction processing, aggregation queries, and geospatial queries
Collection Operations
Collection Operations provide a direct and flexible database access method, suitable for rapid development and prototype validation.
Initialize Database
- SDK Initialization
- Collection Reference
const tcb = require('@cloudbase/node-sdk');
exports.main = async (event, context) => {
// Initialize CloudBase
const app = tcb.init({
env: tcb.SYMBOL_CURRENT_ENV // Use the current environment
});
// Obtain a database instance
const db = app.database();
const _ = db.command; // Obtain the query command
// Your business logic
return { success: true };
};
const tcb = require('@cloudbase/node-sdk');
exports.main = async (event, context) => {
const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV });
const db = app.database();
// Obtain the collection reference
const usersCollection = db.collection('users');
const ordersCollection = db.collection('orders');
const productsCollection = db.collection('products');
// Use collections for operations
const user = await usersCollection.doc('user-123').get();
return { user: user.data };
};
Data Query
- Single Query
- Multiple Query
- Complex Query
const tcb = require('@cloudbase/node-sdk');
exports.main = async (event, context) => {
const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV });
const db = app.database();
try {
// Query a single record by document ID
const result = await db.collection('users')
.doc(event.userId)
.get();
if (result.data.length === 0) {
return {
success: false,
error: 'User does not exist'
};
}
const user = result.data[0];
return {
success: true,
user: {
id: user._id,
name: user.name,
email: user.email,
createdAt: user.createdAt
}
};
} catch (error) {
console.error('Failed to query user:', error);
return {
success: false,
error: error.message
};
}
};
const tcb = require('@cloudbase/node-sdk');
exports.main = async (event, context) => {
const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV });
const db = app.database();
const _ = db.command;
try {
// Build query conditions
const { status, category, page = 1, pageSize = 10 } = event;
let query = db.collection('products');
// Add filter conditions
const conditions = {};
if (status) {
conditions.status = status;
}
if (category) {
conditions.category = category;
}
// Execute the query
const result = await query
.where(conditions)
.orderBy('createdAt', 'desc')
.skip((page - 1) * pageSize)
.limit(pageSize)
.field({
name: true,
price: true,
category: true,
status: true,
createdAt: true
})
.get();
// Obtain the total count (for pagination)
const countResult = await query.where(conditions).count();
return {
success: true,
data: {
products: result.data,
pagination: {
page,
pageSize,
total: countResult.total,
totalPages: Math.ceil(countResult.total / pageSize)
}
}
};
} catch (error) {
console.error('Failed to query product:', error);
return {
success: false,
error: error.message
};
}
};
const tcb = require('@cloudbase/node-sdk');
exports.main = async (event, context) => {
const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV });
const db = app.database();
const _ = db.command;
try {
// Complex query conditions
const result = await db.collection('orders')
.where({
// Order status is paid or shipped
status: _.in(['paid', 'shipped']),
// Order amount is greater than 100
totalAmount: _.gt(100),
// Creation time is within the last 30 days
createdAt: _.gte(new Date(Date.now() - 30 * 24 * 60 * 60 * 1000)),
// User level is VIP or SVIP
'user.level': _.in(['VIP', 'SVIP'])
})
.orderBy('createdAt', 'desc')
.limit(50)
.get();
// Data statistics
const stats = {
totalOrders: result.data.length,
totalAmount: result.data.reduce((sum, order) => sum + order.totalAmount, 0),
averageAmount: 0
};
if (stats.totalOrders > 0) {
stats.averageAmount = stats.totalAmount / stats.totalOrders;
}
return {
success: true,
orders: result.data,
statistics: stats
};
} catch (error) {
console.error('Complex query failed:', error);
return {
success: false,
error: error.message
};
}
};
Data Operations
- Data Creation
- Data Update
- Delete Data
- Batch Operations
const tcb = require('@cloudbase/node-sdk');
exports.main = async (event, context) => {
const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV });
const db = app.database();
try {
// Create a single record
const newUser = {
name: event.name,
email: event.email,
phone: event.phone,
status: 'active',
createdAt: new Date(),
updatedAt: new Date(),
profile: {
avatar: event.avatar || '',
bio: event.bio || '',
preferences: {
language: 'zh-CN',
timezone: 'Asia/Shanghai'
}
}
};
const result = await db.collection('users').add(newUser);
return {
success: true,
userId: result.id,
message: 'User created successfully'
};
} catch (error) {
console.error('Failed to create user:', error);
return {
success: false,
error: error.message
};
}
};
const tcb = require('@cloudbase/node-sdk');
exports.main = async (event, context) => {
const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV });
const db = app.database();
const _ = db.command;
try {
const { userId, updateData } = event;
// Build update data
const updateFields = {
updatedAt: new Date()
};
// Safely update allowed fields
const allowedFields = ['name', 'phone', 'avatar', 'bio'];
allowedFields.forEach(field => {
if (updateData[field] !== undefined) {
updateFields[field] = updateData[field];
}
});
// Update nested fields
if (updateData.preferences) {
updateFields['profile.preferences'] = updateData.preferences;
}
// Execute the update
const result = await db.collection('users')
.doc(userId)
.update(updateFields);
if (result.updated === 0) {
return {
success: false,
error: 'User does not exist or no update needed'
};
}
return {
success: true,
message: 'User information updated successfully'
};
} catch (error) {
console.error('Failed to update user:', error);
return {
success: false,
error: error.message
};
}
};
const tcb = require('@cloudbase/node-sdk');
exports.main = async (event, context) => {
const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV });
const db = app.database();
try {
const { userId, softDelete = true } = event;
if (softDelete) {
// Soft delete: marked as deleted
const result = await db.collection('users')
.doc(userId)
.update({
status: 'deleted',
deletedAt: new Date(),
updatedAt: new Date()
});
return {
success: true,
message: 'User marked for deletion'
};
} else {
// Hard delete: Physically delete the record
const result = await db.collection('users')
.doc(userId)
.remove();
if (result.deleted === 0) {
return {
success: false,
error: 'User does not exist'
};
}
return {
success: true,
message: 'User permanently deleted'
};
}
} catch (error) {
console.error('Failed to delete user:', error);
return {
success: false,
error: error.message
};
}
};
const tcb = require('@cloudbase/node-sdk');
exports.main = async (event, context) => {
const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV });
const db = app.database();
try {
const { operation, data } = event;
switch (operation) {
case 'batchCreate':
// Batch Creation
const createPromises = data.map(item =>
db.collection('products').add({
...item,
createdAt: new Date(),
updatedAt: new Date()
})
);
const createResults = await Promise.allSettled(createPromises);
const successCount = createResults.filter(r => r.status === 'fulfilled').length;
return {
success: true,
message: `Successfully created ${successCount}/${data.length} records`
};
case 'batchUpdate':
// Batch Update
const updatePromises = data.map(item =>
db.collection('products')
.doc(item.id)
.update({
...item.updateData,
updatedAt: new Date()
})
);
const updateResults = await Promise.allSettled(updatePromises);
const updateSuccessCount = updateResults.filter(r => r.status === 'fulfilled').length;
return {
success: true,
message: `Successfully updated ${updateSuccessCount}/${data.length} records`
};
case 'batchDelete':
// Batch Deletion
const deletePromises = data.map(id =>
db.collection('products').doc(id).remove()
);
const deleteResults = await Promise.allSettled(deletePromises);
const deleteSuccessCount = deleteResults.filter(r => r.status === 'fulfilled').length;
return {
success: true,
message: `Successfully deleted ${deleteSuccessCount}/${data.length} records`
};
default:
return {
success: false,
error: 'Unsupported batch operation type'
};
}
} catch (error) {
console.error('Batch operation failed:', error);
return {
success: false,
error: error.message
};
}
};
Data Model Operations
Data models provide structured data access methods, supporting type validation, field constraints, and associated queries.
Initialize Data Model
const tcb = require('@cloudbase/node-sdk');
exports.main = async (event, context) => {
const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV });
// Obtain data model instance
const models = app.models;
// Access specific data model
const userModel = models.user;
const orderModel = models.order;
const productModel = models.product;
// Your business logic
return { success: true };
};
Data Model Query
- Single Query
- Multiple Query
- Join Query
const tcb = require('@cloudbase/node-sdk');
exports.main = async (event, context) => {
const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV });
const models = app.models;
try {
// Query single user record
const result = await models.user.get({
filter: {
where: {
_id: {
$eq: event.userId
}
}
},
select: {
$master: true // Return all fields
}
});
if (result.data.records.length === 0) {
return {
success: false,
error: 'User does not exist'
};
}
const user = result.data.records[0];
return {
success: true,
user: user
};
} catch (error) {
console.error('Failed to query user:', error);
return {
success: false,
error: error.message
};
}
};
const tcb = require('@cloudbase/node-sdk');
exports.main = async (event, context) => {
const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV });
const models = app.models;
try {
const { status, page = 1, pageSize = 10 } = event;
// Build query conditions
const whereCondition = {};
if (status) {
whereCondition.status = { $eq: status };
}
// Query order list
const result = await models.order.list({
filter: {
where: whereCondition,
orderBy: [
{ field: 'createdAt', direction: 'desc' }
],
offset: (page - 1) * pageSize,
limit: pageSize
},
select: {
_id: true,
orderNumber: true,
totalAmount: true,
status: true,
createdAt: true,
user: {
name: true,
email: true
}
}
});
return {
success: true,
data: {
orders: result.data.records,
pagination: {
page,
pageSize,
total: result.data.total,
totalPages: Math.ceil(result.data.total / pageSize)
}
}
};
} catch (error) {
console.error('Query order list failed:', error);
return {
success: false,
error: error.message
};
}
};
const tcb = require('@cloudbase/node-sdk');
exports.main = async (event, context) => {
const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV });
const models = app.models;
try {
// Query orders and their associated user and product information
const result = await models.order.list({
filter: {
where: {
status: { $eq: 'completed' }
},
orderBy: [
{ field: 'createdAt', direction: 'desc' }
],
limit: 20
},
select: {
_id: true,
orderNumber: true,
totalAmount: true,
status: true,
createdAt: true,
// Query associated user information
user: {
_id: true,
name: true,
email: true,
phone: true
},
// Join query order items and product information
orderItems: {
quantity: true,
price: true,
product: {
_id: true,
name: true,
category: true,
image: true
}
}
}
});
// Data processing and statistics
const orders = result.data.records.map(order => ({
...order,
itemCount: order.orderItems.length,
customerInfo: {
name: order.user.name,
contact: order.user.email || order.user.phone
}
}));
return {
success: true,
orders: orders,
summary: {
totalOrders: orders.length,
totalRevenue: orders.reduce((sum, order) => sum + order.totalAmount, 0)
}
};
} catch (error) {
console.error('Join query failed:', error);
return {
success: false,
error: error.message
};
}
};
Data Model Operations
- Data Creation
- Data Update
- Delete Data
const tcb = require('@cloudbase/node-sdk');
exports.main = async (event, context) => {
const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV });
const models = app.models;
try {
// Create a new order
const orderData = {
orderNumber: `ORD${Date.now()}`,
userId: event.userId,
items: event.items,
totalAmount: event.totalAmount,
shippingAddress: event.shippingAddress,
status: 'pending',
paymentMethod: event.paymentMethod,
notes: event.notes || ''
};
const result = await models.order.create({
data: orderData
});
return {
success: true,
orderId: result.data._id,
orderNumber: orderData.orderNumber,
message: 'Order created successfully'
};
} catch (error) {
console.error('Order creation failed:', error);
return {
success: false,
error: error.message
};
}
};
const tcb = require('@cloudbase/node-sdk');
exports.main = async (event, context) => {
const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV });
const models = app.models;
try {
const { orderId, updateData } = event;
// Update order status
const result = await models.order.update({
filter: {
where: {
_id: { $eq: orderId }
}
},
data: {
status: updateData.status,
trackingNumber: updateData.trackingNumber,
shippedAt: updateData.status === 'shipped' ? new Date() : undefined,
deliveredAt: updateData.status === 'delivered' ? new Date() : undefined,
notes: updateData.notes
}
});
if (result.data.updated === 0) {
return {
success: false,
error: 'Order does not exist or no update needed'
};
}
return {
success: true,
message: 'Order status updated successfully'
};
} catch (error) {
console.error('Order update failed:', error);
return {
success: false,
error: error.message
};
}
};
const tcb = require('@cloudbase/node-sdk');
exports.main = async (event, context) => {
const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV });
const models = app.models;
try {
const { orderId } = event;
// Check whether the order status allows deletion.
const orderResult = await models.order.get({
filter: {
where: {
_id: { $eq: orderId }
}
},
select: {
status: true
}
});
if (orderResult.data.records.length === 0) {
return {
success: false,
error: 'Order does not exist'
};
}
const order = orderResult.data.records[0];
const deletableStatuses = ['pending', 'cancelled'];
if (!deletableStatuses.includes(order.status)) {
return {
success: false,
error: 'Current order status does not allow deletion'
};
}
// Delete order
const result = await models.order.delete({
filter: {
where: {
_id: { $eq: orderId }
}
}
});
return {
success: true,
message: 'Order deleted successfully'
};
} catch (error) {
console.error('Order deletion failed:', error);
return {
success: false,
error: error.message
};
}
};
Advanced Features
Transaction Processing
const tcb = require('@cloudbase/node-sdk');
exports.main = async (event, context) => {
const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV });
const db = app.database();
try {
// Start the transaction.
const transaction = await db.startTransaction();
try {
const { fromUserId, toUserId, amount } = event;
// 1. Check the transferring user's balance
const fromUserResult = await transaction.collection('users')
.doc(fromUserId)
.get();
if (fromUserResult.data[0].balance < amount) {
throw new Error('Insufficient balance');
}
// 2. Deduct the transfer-out user balance
await transaction.collection('users')
.doc(fromUserId)
.update({
balance: db.command.inc(-amount),
updatedAt: new Date()
});
// 3. Increase the transfer-in user's balance
await transaction.collection('users')
.doc(toUserId)
.update({
balance: db.command.inc(amount),
updatedAt: new Date()
});
// 4. Log the transfer
await transaction.collection('transactions').add({
fromUserId,
toUserId,
amount,
type: 'transfer',
status: 'completed',
createdAt: new Date()
});
// Commit the transaction.
await transaction.commit();
return {
success: true,
message: 'Transfer succeeded'
};
} catch (error) {
// Roll back the transaction.
await transaction.rollback();
throw error;
}
} catch (error) {
console.error('Transfer failed:', error);
return {
success: false,
error: error.message
};
}
};
Aggregation Query
const tcb = require('@cloudbase/node-sdk');
exports.main = async (event, context) => {
const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV });
const db = app.database();
try {
// Sales Data Statistics
const salesStats = await db.collection('orders')
.aggregate()
.match({
status: 'completed',
createdAt: {
$gte: new Date(event.startDate),
$lte: new Date(event.endDate)
}
})
.group({
_id: {
year: { $year: '$createdAt' },
month: { $month: '$createdAt' },
day: { $dayOfMonth: '$createdAt' }
},
totalOrders: { $sum: 1 },
totalRevenue: { $sum: '$totalAmount' },
averageOrderValue: { $avg: '$totalAmount' },
maxOrderValue: { $max: '$totalAmount' },
minOrderValue: { $min: '$totalAmount' }
})
.sort({
'_id.year': 1,
'_id.month': 1,
'_id.day': 1
})
.end();
// Product Sales Statistics
const productStats = await db.collection('orders')
.aggregate()
.match({
status: 'completed'
})
.unwind('$items')
.group({
_id: '$items.productId',
totalSold: { $sum: '$items.quantity' },
totalRevenue: { $sum: { $multiply: ['$items.quantity', '$items.price'] } },
orderCount: { $sum: 1 }
})
.lookup({
from: 'products',
localField: '_id',
foreignField: '_id',
as: 'product'
})
.unwind('$product')
.project({
productName: '$product.name',
category: '$product.category',
totalSold: 1,
totalRevenue: 1,
orderCount: 1,
averagePrice: { $divide: ['$totalRevenue', '$totalSold'] }
})
.sort({ totalRevenue: -1 })
.limit(10)
.end();
return {
success: true,
data: {
dailySales: salesStats.list,
topProducts: productStats.list
}
};
} catch (error) {
console.error('Aggregation query failed:', error);
return {
success: false,
error: error.message
};
}
};
Geographic Location Query
const tcb = require('@cloudbase/node-sdk');
exports.main = async (event, context) => {
const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV });
const db = app.database();
const _ = db.command;
try {
const { longitude, latitude, radius = 5000 } = event; // Default 5 kilometers
// Query nearby stores
const nearbyStores = await db.collection('stores')
.where({
location: _.geoNear({
geometry: new db.Geo.Point(longitude, latitude),
maxDistance: radius,
minDistance: 0
}),
status: 'active'
})
.field({
name: true,
address: true,
phone: true,
location: true,
businessHours: true,
services: true
})
.get();
// Calculate distance and sort
const storesWithDistance = nearbyStores.data.map(store => {
const distance = calculateDistance(
latitude, longitude,
store.location.coordinates[1], store.location.coordinates[0]
);
return {
...store,
distance: Math.round(distance)
};
}).sort((a, b) => a.distance - b.distance);
// Query the delivery area within the specified region
const deliveryArea = new db.Geo.Polygon([
new db.Geo.LineString([
new db.Geo.Point(longitude - 0.01, latitude - 0.01),
new db.Geo.Point(longitude + 0.01, latitude - 0.01),
new db.Geo.Point(longitude + 0.01, latitude + 0.01),
new db.Geo.Point(longitude - 0.01, latitude + 0.01),
new db.Geo.Point(longitude - 0.01, latitude - 0.01)
])
]);
const deliveryStores = await db.collection('stores')
.where({
deliveryArea: _.geoIntersects({
geometry: deliveryArea
}),
deliveryEnabled: true
})
.get();
return {
success: true,
data: {
nearbyStores: storesWithDistance,
deliveryAvailable: deliveryStores.data.length > 0,
deliveryStores: deliveryStores.data
}
};
} catch (error) {
console.error('Geolocation query failed:', error);
return {
success: false,
error: error.message
};
}
};
// Calculate the distance between two points (in meters)
function calculateDistance(lat1, lon1, lat2, lon2) {
const R = 6371e3; // Earth radius (meters)
const φ1 = lat1 * Math.PI / 180;
const φ2 = lat2 * Math.PI / 180;
const Δφ = (lat2 - lat1) * Math.PI / 180;
const Δλ = (lon2 - lon1) * Math.PI / 180;
const a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
Math.cos(φ1) * Math.cos(φ2) *
Math.sin(Δλ/2) * Math.sin(Δλ/2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
return R * c;
}
Data Monitoring and Real-time Synchronization
const tcb = require('@cloudbase/node-sdk');
exports.main = async (event, context) => {
const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV });
const db = app.database();
try {
// Listen for order status changes
const watcher = db.collection('orders')
.where({
userId: event.userId,
status: db.command.in(['pending', 'processing', 'shipped'])
})
.watch({
onChange: (snapshot) => {
console.log('Order status changes:', snapshot);
// Handle changing documents
snapshot.docChanges.forEach(change => {
const { doc, queueType } = change;
switch (queueType) {
case 'init':
console.log('Initialize order:', doc.data());
break;
case 'update':
console.log('Order update:', doc.data());
// Send status update notification
sendOrderStatusNotification(doc.data());
break;
case 'add':
console.log('New order:', doc.data());
break;
case 'remove':
console.log('Order deletion:', doc.data());
break;
}
});
},
onError: (error) => {
console.error('Listen error:', error);
}
});
// Stop listening before the cloud function terminates
// watcher.close();
return {
success: true,
message: 'Order listening has started'
};
} catch (error) {
console.error('Failed to set data listening:', error);
return {
success: false,
error: error.message
};
}
};
async function sendOrderStatusNotification(order) {
// Logic for sending order status update notifications
console.log(`Sending notification: Order ${order.orderNumber} status updated to ${order.status}`);
}
Performance Optimization Recommendations
1. Index Optimization
const tcb = require('@cloudbase/node-sdk');
exports.main = async (event, context) => {
const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV });
const db = app.database();
try {
// Create a composite index
await db.collection('orders').createIndex({
keys: {
userId: 1,
status: 1,
createdAt: -1
},
options: {
name: 'user_status_time_index',
background: true
}
});
// Create a geolocation index
await db.collection('stores').createIndex({
keys: {
location: '2dsphere'
},
options: {
name: 'location_index'
}
});
// Create a text search index
await db.collection('products').createIndex({
keys: {
name: 'text',
description: 'text',
tags: 'text'
},
options: {
name: 'text_search_index',
weights: {
name: 10,
description: 5,
tags: 1
}
}
});
return {
success: true,
message: 'Index created successfully'
};
} catch (error) {
console.error('Failed to create index:', error);
return {
success: false,
error: error.message
};
}
};
2. Query Optimization
const tcb = require('@cloudbase/node-sdk');
exports.main = async (event, context) => {
const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV });
const db = app.database();
try {
// Optimize queries: Use projection to reduce data transfer
const result = await db.collection('orders')
.where({
userId: event.userId,
status: 'completed'
})
.field({
// Return only the required fields
orderNumber: true,
totalAmount: true,
createdAt: true,
// Exclude large fields
items: false,
shippingAddress: false
})
.orderBy('createdAt', 'desc')
.limit(20)
.get();
// Use aggregation pipeline to optimize complex queries
const stats = await db.collection('orders')
.aggregate()
.match({
userId: event.userId,
createdAt: {
$gte: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000)
}
})
.group({
_id: null,
totalOrders: { $sum: 1 },
totalAmount: { $sum: '$totalAmount' },
averageAmount: { $avg: '$totalAmount' }
})
.end();
return {
success: true,
orders: result.data,
statistics: stats.list[0] || {
totalOrders: 0,
totalAmount: 0,
averageAmount: 0
}
};
} catch (error) {
console.error('Query optimization failed:', error);
return {
success: false,
error: error.message
};
}
};
3. Connection Pool Management
const tcb = require('@cloudbase/node-sdk');
// Global initialization, reuse connections
const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV });
const db = app.database();
exports.main = async (event, context) => {
try {
// Use a global database instance to avoid repeated initialization
const result = await db.collection('users')
.doc(event.userId)
.get();
return {
success: true,
user: result.data[0]
};
} catch (error) {
console.error('Database operation failed:', error);
return {
success: false,
error: error.message
};
}
};
Error Handling and Debugging
Common Error Handling
const tcb = require('@cloudbase/node-sdk');
exports.main = async (event, context) => {
const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV });
const db = app.database();
try {
const result = await db.collection('users')
.doc(event.userId)
.get();
return {
success: true,
user: result.data[0]
};
} catch (error) {
console.error('Database operation failed:', {
error: error.message,
code: error.code,
requestId: error.requestId,
stack: error.stack
});
// Return different responses based on error types
switch (error.code) {
case 'PERMISSION_DENIED':
return {
success: false,
error: 'Insufficient permissions',
code: 'PERMISSION_DENIED'
};
case 'INVALID_PARAM':
return {
success: false,
error: 'Invalid parameter',
code: 'INVALID_PARAM'
};
case 'NETWORK_ERROR':
return {
success: false,
error: 'Network connection failed, please try again later',
code: 'NETWORK_ERROR'
};
default:
return {
success: false,
error: 'Database operation failed',
code: error.code || 'UNKNOWN_ERROR'
};
}
}
};