在Mongo/Mongoose中自动增加文档编号

rag*_*lka 8 mongoose mongodb

我的应用有几个用户,每个用户都有文档.每个文档都需要有一个序列号,可能看起来像这样:2013-1,2013-2(年份和序列号),或者只是一个简单的数字:1,2,3 ......

目前,我在创建Mongoose docuemnt时从用户的设置中分配序列号.根据序列号和用户设置的数字格式,我生成最终的文档编号.

我意识到,当同时创建2个文档时,它们将得到完全相同的数字,因为我在保存文档后刚刚在设置中递增序列号.但是,当我创建(不保存)文档时,我正在分配序列号,因此两个文档的序列号将完全相同.

我显然需要一种方法来处理这个序列号在保存时自动递增...

如何确保此数字是唯一的并自动递增/生成?

rag*_*lka 12

@emre和@WiredPraire向我指出了正确的方向,但我想为我的问题提供一个完整的Mongoose兼容的答案.我最终得到了以下解决方案:

var Settings = new Schema({
  nextSeqNumber: { type: Number, default: 1 }
});

var Document = new Schema({
  _userId: { type: Schema.Types.ObjectId, ref: "User" },
  number: { type: String }
});

// Create a compound unique index over _userId and document number
Document.index({ "_userId": 1, "number": 1 }, { unique: true });

// I make sure this is the last pre-save middleware (just in case)
Document.pre('save', function(next) {
  var doc = this;
  // You have to know the settings_id, for me, I store it in memory: app.current.settings.id
  Settings.findByIdAndUpdate( settings_id, { $inc: { nextSeqNumber: 1 } }, function (err, settings) {
    if (err) next(err);
    doc.number = settings.nextSeqNumber - 1; // substract 1 because I need the 'current' sequence number, not the next
    next();
  });
});
Run Code Online (Sandbox Code Playgroud)

请注意,使用此方法无法在架构中要求数字路径,也没有任何意义,因为它会自动添加.

  • 感谢您发布代码示例,这看起来像我一直在寻找的解决方案.如果这对任何人都有用,我也对它进行了调整,以便只在为创建而不是更新调用save时生成ID:if(doc.isNew){Settings.findByIdAndUpdate ...} else {next(); } (3认同)
  • +1!要详细说明为什么会这样,你需要一个阻塞操作(例如,写一个),以便异步的`save()`调用按顺序进行.使用查找或计数您希望递增的集合的"更简单"解决方案失败,因为查找和计数都是非阻塞(读取命令),因此您不能依赖它们与(可能)多个异步串行`save()`调用. (2认同)