我的应用有几个用户,每个用户都有文档。每个文档都需要有一个序列号,可能看起来像这样:2013-1,2013-2(年份和序列号),或者只是一个简单的数字:1,2,3 ...
目前,我在创建Mongoose docuemnt时从用户的设置中分配序列号。根据该序列号和用户设置的数字格式,我将生成最终的文档编号。
我意识到,当同时创建2个文档时,它们将获得完全相同的数字,因为我在保存文档后刚刚在设置中递增序列号。但是我在创建(不保存)文档时分配序列号,因此两个文档的序列号将完全相同。
我显然需要一种方法来处理这个序列号在保存时自动递增...
如何确保此号码是唯一的并自动递增/生成?
答案 0 :(得分:11)
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();
});
});
请注意,使用此方法无法在架构中要求数字路径,也没有任何意义,因为它会自动添加。
答案 1 :(得分:3)
您可以通过以下方式实现这一目标:
这是一个使用todo app的工作和测试示例。
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/todoApp');
// Create a sequence
function sequenceGenerator(name){
var SequenceSchema, Sequence;
SequenceSchema = new mongoose.Schema({
nextSeqNumber: { type: Number, default: 1 }
});
Sequence = mongoose.model(name + 'Seq', SequenceSchema);
return {
next: function(callback){
Sequence.find(function(err, data){
if(err){ throw(err); }
if(data.length < 1){
// create if doesn't exist create and return first
Sequence.create({}, function(err, seq){
if(err) { throw(err); }
callback(seq.nextSeqNumber);
});
} else {
// update sequence and return next
Sequence.findByIdAndUpdate(data[0]._id, { $inc: { nextSeqNumber: 1 } }, function(err, seq){
if(err) { throw(err); }
callback(seq.nextSeqNumber);
});
}
});
}
};
}
// sequence instance
var sequence = sequenceGenerator('todo');
var TodoSchema = new mongoose.Schema({
name: String,
completed: Boolean,
priority: Number,
note: { type: String, default: '' },
updated_at: { type: Date, default: Date.now }
});
TodoSchema.pre('save', function(next){
var doc = this;
// get the next sequence
sequence.next(function(nextSeq){
doc.priority = nextSeq;
next();
});
});
var Todo = mongoose.model('Todo', TodoSchema);
您可以在节点控制台中测试它,如下所示
function cb(err, data){ console.log(err, data); }
Todo.create({name: 'hola'}, cb);
Todo.find(cb);
对于每个新创建的对象,您将看到优先级增加。干杯!
答案 2 :(得分:2)
此代码取自MongoDB手册,它实际上描述了使_id字段自动增加。但是,它可以应用于任何领域。您想要的是在插入文档后检查插入的值是否存在于数据库中。如果已经插入,则重新递增该值,然后再次尝试插入。这样,您可以检测到dublicate值并重新递增它们。
while (1) {
var cursor = targetCollection.find( {}, { f: 1 } ).sort( { f: -1 } ).limit(1);
var seq = cursor.hasNext() ? cursor.next().f + 1 : 1;
doc.f = seq;
targetCollection.insert(doc);
var err = db.getLastErrorObj();
if( err && err.code ) {
if( err.code == 11000 /* dup key */ )
continue;
else
print( "unexpected error inserting data: " + tojson( err ) );
}
break;
}
在此示例中,f是文档中要自动递增的字段。为了完成这项工作,你需要使用UNIQUE来完成索引。
db.myCollection.ensureIndex( { "f": 1 }, { unique: true } )
答案 3 :(得分:2)
您可以按如下方式使用mongoose-auto-increment
包:
var mongoose = require('mongoose');
var autoIncrement = require('mongoose-auto-increment');
/* connect to your database here */
/* define your DocumentSchema here */
autoIncrement.initialize(mongoose.connection);
DocumentSchema.plugin(autoIncrement.plugin, 'Document');
var Document = mongoose.model('Document', DocumentSchema);
您只需要初始化autoIncrement
一次。