如何创建人类可读的MongoDB记录ID?以及如何实现从1开始的自增自定义ID?
MongoDB自定义ID解决方案:可读ID与自增整数ID
嘿,针对你提到的两个MongoDB ID相关需求,我来给你一步步拆解可行的解决方案:
一、创建人类可读的MongoDB记录ID
MongoDB默认生成的ObjectId(比如60d21b4667d0d8992e610c85)虽然性能优异且分布式友好,但确实不够直观易读。想要生成人类可读的ID,你可以试试这几种思路:
结合业务语义的自定义字符串ID
把业务相关的标识、时间戳、序列号等组合起来,既保证唯一性,又能一眼看出含义。比如针对用户记录可以用user_001_20240520,针对订单可以用order_20240520_10001。插入时直接指定_id字段即可:db.users.insertOne({ _id: "user_001_20240520", username: "john_doe", email: "john@example.com" });UUID字符串ID
用UUID生成标准的、唯一的字符串ID,可读性比ObjectId好很多,而且跨系统兼容性强。你可以在客户端生成(比如用编程语言的UUID库),或者直接用MongoDB的内置函数:// MongoDB Shell中生成UUID字符串 db.documents.insertOne({ _id: UUID().toString(), content: "Hello World" });
二、实现从1开始的自增整数ID
MongoDB没有内置的自增主键功能,但我们可以通过计数器集合+原子操作来实现安全的自增ID,步骤如下:
1. 创建计数器集合
首先新建一个专门用来维护自增序列的集合(比如叫counters),插入初始的计数器文档:
db.counters.insertOne({ _id: "global_seq", // 可以为不同集合设置不同的计数器,比如"user_seq"、"product_seq" seq: 0 // 初始值设为0,这样第一个ID会是1 });
2. 定义获取自增ID的函数
写一个原子操作的函数,保证在并发场景下不会出现重复ID(核心是用findAndModify或updateOne的原子更新):
function getNextSequence(sequenceName) { const result = db.counters.findAndModify({ query: { _id: sequenceName }, update: { $inc: { seq: 1 } }, // 原子递增 new: true, // 返回更新后的文档 upsert: true // 如果计数器不存在则自动创建 }); return result.seq; }
3. 插入文档时使用自增ID
每次插入新记录时,调用上面的函数获取下一个ID,赋值给_id字段:
// 插入第一条记录,_id会是1 db.products.insertOne({ _id: getNextSequence("global_seq"), name: "Wireless Mouse", price: 29.99 }); // 插入第二条记录,_id会是2 db.products.insertOne({ _id: getNextSequence("global_seq"), name: "Mechanical Keyboard", price: 89.99 });
注意事项
- 原子操作是关键:绝对不要先查询当前最大值再手动递增,高并发场景下会导致ID重复。
- 性能权衡:自增ID每次插入都要操作计数器集合,在超高并发场景下可能成为瓶颈,而默认的ObjectId更适合分布式环境。
- 多集合支持:如果不同集合需要独立的自增序列,只需要给计数器设置不同的
_id即可(比如"user_seq"对应用户集合,"order_seq"对应订单集合)。
内容的提问来源于stack exchange,提问作者Nurul Islam
相关产品推荐
相关产品推荐

