You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Mongoose模型的_id字段设为Number并自动生成序号

解决Mongoose中_id从ObjectId改为自增Number的问题

只在Schema里声明_id: Number不会生效,因为Mongoose默认会自动生成ObjectId作为_id,且不会自动填充数字类型的序号值。要实现自增数字_id,需要借助计数器集合来保证序号的连续性和原子性,具体步骤如下:

1. 创建计数器集合

这个集合用来记录每个业务集合的当前最大序号,避免并发场景下出现重复序号:

const counterSchema = new mongoose.Schema({
  _id: { type: String, required: true }, // 存储对应业务集合的名称
  seq: { type: Number, default: 0 } // 当前序号值
});
const Counter = mongoose.model('Counter', counterSchema);

2. 在目标模型中添加自增逻辑

通过pre('save')钩子,在保存新文档前自动获取并递增序号,赋值给_id:

const mySchema = new mongoose.Schema({
  _id: { type: Number, required: true }
  // 这里添加你的其他字段
});

mySchema.pre('save', async function(next) {
  // 仅处理新增文档的情况
  if (this.isNew) {
    try {
      // 原子性更新计数器:不存在则创建,存在则序号+1
      const counter = await Counter.findOneAndUpdate(
        { _id: 'MyModel' }, // 替换为你的模型对应的集合名称
        { $inc: { seq: 1 } },
        { new: true, upsert: true }
      );
      // 将递增后的序号赋值给当前文档的_id
      this._id = counter.seq;
      next();
    } catch (err) {
      next(err);
    }
  } else {
    next();
  }
});

const MyModel = mongoose.model('MyModel', mySchema);

注意事项

  • 若业务集合已有数据,需先手动初始化计数器的seq值为现有文档的最大_id,避免序号冲突
  • 不要手动给_id赋值,否则会覆盖钩子的自增逻辑
  • findOneAndUpdate的原子性操作能保证多并发场景下不会出现重复序号

内容的提问来源于stack exchange,提问作者Ankur Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 23:03:14