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

MongoDB ObjectID生成疑问:仅计数器变化及跨模型共享原因

关于Mongoose生成ObjectID的两个疑问

根据MongoDB官方文档,ObjectID是一个96位数字,由以下部分构成:

  • 4字节时间戳,代表自Unix纪元以来的秒数(可用至2106年)
  • 5字节随机值
  • 3字节自增计数器,初始值为随机数

疑问1:批量生成ObjectID时仅计数器部分变化

执行以下代码生成1000个ObjectID:

const mongoose = require('mongoose');
const carSchema = new mongoose.Schema({ driver: mongoose.ObjectId });

const Car = mongoose.model('Car', carSchema);

const car = new Car();

let i = 0;
while (i < 1000) {
  car.driver = new mongoose.Types.ObjectId();
  console.log(car.driver.toString());
  i++;
}

预期会看到三部分均有变化,但实际仅计数器部分递增:

~/tmp$ head t2 
638f7d3f37664dec556b0491
638f7d3f37664dec556b0492
638f7d3f37664dec556b0493
638f7d3f37664dec556b0494
638f7d3f37664dec556b0495
638f7d3f37664dec556b0496
638f7d3f37664dec556b0497
638f7d3f37664dec556b0498
638f7d3f37664dec556b0499
638f7d3f37664dec556b049a
~/tmp$ tail t2 
638f7d3f37664dec556b086f
638f7d3f37664dec556b0870
638f7d3f37664dec556b0871
638f7d3f37664dec556b0872
638f7d3f37664dec556b0873
638f7d3f37664dec556b0874
638f7d3f37664dec556b0875
638f7d3f37664dec556b0876
638f7d3f37664dec556b0877
638f7d3f37664dec556b0878

请问为何不会出现三部分均变化的情况?


疑问2:不同模型生成ObjectID共享同一计数器

执行以下代码:

const mongoose = require('mongoose');
const carSchema = new mongoose.Schema({ driver: mongoose.ObjectId });
const carSchema2 = new mongoose.Schema({ driver: mongoose.ObjectId });
const Car = mongoose.model('Car', carSchema);
const Car2 = mongoose.model('Car2', carSchema2);
const car = new Car();
const car2 = new Car2();

const splitElements = id => {
   return {
      seconds: parseInt(id.slice(0, 8), 16),
      random: parseInt(id.slice(8, 18), 16),
      counter: parseInt(id.slice(18, 24), 16),
   };
};

const sleep = ms => {
   return new Promise(resolve => setTimeout(resolve, ms));
};

(async () => {
   let i = 0;
   while (i < 5) {
      car.driver = new mongoose.Types.ObjectId();
      console.log(car.driver.toString(), JSON.stringify(splitElements(car.driver.toString())));
      await sleep(100);
      i++;
   }
})();

(async () => {
   let i = 0;
   while (i < 5) {
      car2.driver = new mongoose.Types.ObjectId();
      console.log(car2.driver.toString(), JSON.stringify(splitElements(car2.driver.toString())));
      await sleep(100);
      i++;
   }
})();

输出结果显示计数器从第一个模型的结束值继续递增:

638fe308b0a1fb8a3c22e2e9 {"seconds":1670374152,"random":758631860796,"counter":2286313}
638fe308b0a1fb8a3c22e2ea {"seconds":1670374152,"random":758631860796,"counter":2286314}
638fe308b0a1fb8a3c22e2eb {"seconds":1670374152,"random":758631860796,"counter":2286315}
638fe308b0a1fb8a3c22e2ec {"seconds":1670374152,"random":758631860796,"counter":2286316}
638fe308b0a1fb8a3c22e2ed {"seconds":1670374152,"random":758631860796,"counter":2286317}
638fe308b0a1fb8a3c22e2ee {"seconds":1670374152,"random":758631860796,"counter":2286318}
638fe308b0a1fb8a3c22e2ef {"seconds":1670374152,"random":758631860796,"counter":2286319}
638fe308b0a1fb8a3c22e2f0 {"seconds":1670374152,"random":758631860796,"counter":2286320}
638fe308b0a1fb8a3c22e2f1 {"seconds":1670374152,"random":758631860796,"counter":2286321}
638fe308b0a1fb8a3c22e2f2 {"seconds":1670374152,"random":758631860796,"counter":2286322}

原本预期每个模型对象拥有独立计数器,为何它们会共享同一计数器?


内容的提问来源于stack exchange,提问作者Sandra Schlichting

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 02:01:17