如何使用MongoDB Atlas Data API执行批量更新操作?
解决MongoDB Atlas Data API批量更新不同文档的问题
为什么出现404错误
MongoDB Atlas Data API当前并未提供bulkWrite或类似的批量操作原生端点,你调用的/action/bulkWrite是不存在的接口,因此返回404状态码。
可行的批量更新方案
方案一:分批次调用单个updateOne请求
由于每个文档的更新内容不同,只能逐个调用Data API的updateOne接口。为避免触发API速率限制,需要分批次处理请求:
const axios = require('axios'); // 批量更新函数,带分批限流 async function batchUpdateUsers(userUpdates) { const batchSize = 50; // 每次批量发送的请求数,根据API限制调整 const results = []; for (let i = 0; i < userUpdates.length; i += batchSize) { const batch = userUpdates.slice(i, i + batchSize); // 并行发送当前批次的请求 const batchPromises = batch.map(({ id, value }) => { const requestData = JSON.stringify({ collection: "<collection>", database: "<database>", dataSource: "<datasource>", filter: { _id: { $oid: id } }, update: { $addToSet: { someArray: value } } }); return axios.post( "https://data.mongodb-api.com/app/data-somekey/endpoint/data/v1/action/updateOne", requestData, { headers: { "Content-Type": "application/json", "api-key": "<api_key>" } } ).catch(err => ({ error: err.response.data, id })); }); const batchResults = await Promise.allSettled(batchPromises); results.push(...batchResults); // 批次间添加延迟,避免触发速率限制 if (i + batchSize < userUpdates.length) { await new Promise(resolve => setTimeout(resolve, 500)); } } return results; } // 使用示例:假设userUpdates是包含id和对应更新值的数组 const userUpdates = [ { id: '123', value: 'value1' }, { id: 'abc', value: 'value2' }, // ...更多项 ]; batchUpdateUsers(userUpdates) .then(results => { // 处理结果,筛选成功/失败的请求 const failed = results.filter(r => r.status === 'rejected' || (r.value?.error)); console.log(`批量更新完成,失败数:${failed.length}`); });
注意:需要根据你的Atlas Data API的速率限制调整batchSize和延迟时间,避免被限流。
方案二:使用MongoDB Atlas Functions(推荐大批量场景)
Atlas Functions直接运行在MongoDB云端,能直接调用原生MongoDB的bulkWrite方法,效率远高于通过Data API的HTTP请求,适合数千级别的批量操作:
- 在MongoDB Atlas控制台创建一个新的Function
- 编写函数逻辑:
exports = async function(userUpdates) { const db = context.services.get("<datasource>").db("<database>"); const collection = db.collection("<collection>"); // 构建bulkWrite操作数组 const bulkOps = userUpdates.map(({ id, value }) => ({ updateOne: { filter: { _id: BSON.ObjectId(id) }, update: { $addToSet: { someArray: value } } } })); try { const result = await collection.bulkWrite(bulkOps); return { success: true, result }; } catch (err) { return { success: false, error: err.message }; } };
- 在你的无服务器函数中调用这个Atlas Function:
async function callAtlasFunction(userUpdates) { const response = await axios.post( "https://<region>.aws.data.mongodb-api.com/app/<app-id>/endpoint/v1/action/callFunction", JSON.stringify({ name: "<your-function-name>", arguments: [userUpdates] }), { headers: { "Content-Type": "application/json", "api-key": "<api_key>" } } ); return response.data; } // 使用示例 callAtlasFunction(userUpdates) .then(res => { if (res.success) { console.log(`批量更新成功:${res.result.modifiedCount}条文档被修改`); } else { console.error(`更新失败:${res.error}`); } });
这种方案的优势是:单次请求完成所有批量操作,避免了大量HTTP请求的开销,也不会触发Data API的速率限制。
内容的提问来源于stack exchange,提问作者gjunkie
相关产品推荐
相关产品推荐

