如何避免重启Node.js服务器时重复创建MongoDB初始5条数据?(基于Mongoose实现)
解决MongoDB重启服务重复插入初始化数据的问题
这问题我之前做项目时也碰到过,每次重启服务就自动重复插数据确实挺烦的!咱们可以从这几个实用的方向来解决:
方法一:先检查再插入(最简单的开发环境方案)
核心思路是:每次加载model时,先检查集合里有没有数据,只有当数据为空的时候才执行插入操作。修改你的main-model.js代码如下:
const mongoose = require('mongoose') const Schema = mongoose.Schema const mainSchema = new Schema({ likes:{ type:Number, max:100000 }, people:[{ key:{type:String}, name:{type:String} }] },{ timestamps:true }) const MAIN = mongoose.model('liker-model',mainSchema) // 新增:先检查集合是否为空,再插入初始化数据 MAIN.countDocuments().then(count => { if (count === 0) { MAIN.insertMany([ {"_id":mongoose.Types.ObjectId(1),likes:0,people:[]}, {"_id":mongoose.Types.ObjectId(2),likes:0,people:[]}, {"_id":mongoose.Types.ObjectId(3),likes:0,people:[]}, {"_id":mongoose.Types.ObjectId(4),likes:0,people:[]}, {"_id":mongoose.Types.ObjectId(5),likes:0,people:[]}, ]) .then(() => console.log("初始化数据插入成功")) .catch(err => console.error("初始化插入失败:", err)) } }) module.exports = MAIN
这个方案的优点是改动小,适合开发阶段快速解决问题;缺点是如果以后你手动删除了某几条数据,重启服务时不会自动补全(只会在全空的时候插入)。
方法二:使用bulkWrite+upsert(确保数据存在且不覆盖现有内容)
如果希望不管集合里有没有数据,都只保留这5条固定ID的文档,且不会覆盖已有的修改内容,可以用MongoDB的批量操作结合upsert(不存在则插入,存在则不做修改):
const mongoose = require('mongoose') const Schema = mongoose.Schema const mainSchema = new Schema({ likes:{ type:Number, max:100000 }, people:[{ key:{type:String}, name:{type:String} }] },{ timestamps:true }) const MAIN = mongoose.model('liker-model',mainSchema) // 批量初始化:不存在则插入,存在则跳过 const initDocs = [ {"_id":mongoose.Types.ObjectId(1),likes:0,people:[]}, {"_id":mongoose.Types.ObjectId(2),likes:0,people:[]}, {"_id":mongoose.Types.ObjectId(3),likes:0,people:[]}, {"_id":mongoose.Types.ObjectId(4),likes:0,people:[]}, {"_id":mongoose.Types.ObjectId(5),likes:0,people:[]}, ] const bulkOperations = initDocs.map(doc => ({ updateOne: { filter: { _id: doc._id }, // 按ID匹配 update: { $setOnInsert: doc }, // 只有插入时才设置这些字段 upsert: true // 不存在就插入,存在则不执行任何操作 } })) MAIN.bulkWrite(bulkOperations) .then(result => console.log("初始化完成:", result)) .catch(err => console.error("初始化出错:", err)) module.exports = MAIN
这个方案更灵活,即使你后续修改了某条文档的likes或people字段,重启服务也不会覆盖这些修改,只会补全缺失的固定ID文档。
方法三:将初始化逻辑移到独立脚本(生产环境推荐)
生产环境下,不建议把初始化逻辑放在model里(万一误操作重复执行会有风险),最好把初始化做成一个独立的脚本,只在需要的时候手动执行:
- 新建
init-db.js文件:
const mongoose = require('mongoose'); const MAIN = require('./models/main-model'); // 注意路径要对应你的项目结构 // 连接数据库(请替换成你的实际连接字符串) mongoose.connect('mongodb://localhost:27017/your-db-name') .then(async () => { console.log("数据库连接成功"); // 先检查是否已经存在数据 const count = await MAIN.countDocuments(); if (count > 0) { console.log("数据库已有数据,无需初始化"); process.exit(); } // 执行插入 await MAIN.insertMany([ {"_id":mongoose.Types.ObjectId(1),likes:0,people:[]}, {"_id":mongoose.Types.ObjectId(2),likes:0,people:[]}, {"_id":mongoose.Types.ObjectId(3),likes:0,people:[]}, {"_id":mongoose.Types.ObjectId(4),likes:0,people:[]}, {"_id":mongoose.Types.ObjectId(5),likes:0,people:[]}, ]); console.log("初始化数据插入成功"); process.exit(); }) .catch(err => { console.error("初始化失败:", err); process.exit(1); });
- 在
package.json里添加一个脚本命令:
{ "scripts": { "init-db": "node init-db.js" } }
- 需要初始化数据时,在终端执行:
npm run init-db
这个方案最安全,完全避免了重启服务时自动执行插入的问题,适合生产环境使用。
内容的提问来源于stack exchange,提问作者MYTH
相关产品推荐
相关产品推荐

