如何将Google Calendar API获取的事件批量存入MongoDB并去重验证?
解决Google Calendar事件批量同步到MongoDB的问题
我来帮你搞定把Google Calendar事件批量存到MongoDB的事儿,还能自动基于唯一ID跳过已存在的事件~ 下面是具体的修改步骤和代码:
1. 优化你的EventSchema(可选但推荐)
首先,你的id字段应该设为必填,因为Google返回的每个事件都有唯一ID,这样能避免数据库里出现无ID的无效数据:
const mongoose = require('mongoose'); const Schema = mongoose.Schema; const EventSchema = new Schema({ id: { type: String, required: true, unique:true }, // 把required改为true,确保每个事件都有唯一ID start: { type: String }, end: { type: String }, status: { type: String }, creator: { type: Array }, description: { type: String } }); module.exports = Event = mongoose.model('events', EventSchema);
2. 修改路由代码,实现批量同步
我们会用Mongoose的bulkWrite方法来做批量操作,效率比循环单个保存高很多,同时通过Google事件的id来判断是否已存在。另外把原来的回调改成async/await,代码更易读:
const Event = require('../models/event'); // 记得引入你的Event模型,路径根据实际项目结构调整 router.post("/google/get", async (req, res, next) => { try { const { google } = require('googleapis') const { addWeeks } = require('date-fns') const { OAuth2 } = google.auth const oAuth2Client = new OAuth2( process.env.GOOGLE_CLIENT_ID, process.env.GOOGLE_CLIENT_SECRET ) oAuth2Client.setCredentials({ refresh_token: process.env.GOOGLE_REFRESH_TOKEN, }) const calendar = google.calendar({ version: 'v3', auth: oAuth2Client }) // 用await替代回调,获取Google日历事件 const response = await calendar.events.list({ calendarId: 'MY CALENDAR ID', timeMin: new Date().toISOString(), timeMax: addWeeks(new Date(), 1).toISOString(), singleEvents: true, orderBy: 'startTime', }); const events = response.data.items; if (!events.length) { console.log("没有找到需要同步的事件"); return res.status(200).json({ message: "没有需要同步的事件" }); } // 准备批量操作的数组 const bulkOperations = events.map(event => ({ updateOne: { filter: { id: event.id }, // 用Google事件的唯一ID匹配数据库中的记录 update: { $set: { start: event.start.dateTime || event.start.date, end: event.end.dateTime || event.end.date, status: event.status, creator: [event.creator], // Google返回的creator是单个对象,转成数组匹配你的Schema description: event.description || '' // 处理description为空的情况 } }, upsert: true // 关键参数:true=不存在就插入,存在就更新;false=存在就跳过,只新增 } })); // 执行批量操作 const result = await Event.bulkWrite(bulkOperations); console.log(`同步完成:新增 ${result.insertedCount} 个事件,更新 ${result.modifiedCount} 个已有事件`); res.status(200).json({ message: "事件同步成功", insertedEvents: result.insertedCount, updatedEvents: result.modifiedCount }); } catch (err) { console.error("同步过程出错:", err); res.status(500).json({ error: "事件同步失败", details: err.message }); } });
关键细节说明
bulkWrite的优势:一次性处理所有事件,减少数据库连接次数,比循环调用save()或findOneAndUpdate()效率高得多,适合批量场景。upsert参数:- 如果设为
true:数据库中没有该ID的事件就插入新记录,已有则更新字段(适合需要同步最新事件信息的场景)。 - 如果设为
false:只插入不存在的事件,已有事件直接跳过(适合只新增不更新的场景)。
- 如果设为
- 字段映射:确保Google返回的字段和你的Schema对应,比如
creator是数组类型,所以把Google返回的单个creator对象包裹成数组。 - 错误处理:用
try/catch捕获所有异步操作的错误,包括Google API调用失败和数据库操作失败,返回清晰的错误信息。
内容的提问来源于stack exchange,提问作者vicbruxsel
相关产品推荐
相关产品推荐

