我以通常的方式初始化数据库:
mongoose.connect(`mongodb://uname:pword@127.0.0.1:port/dbname?authSource=admin`, {useNewUrlParser: true, autoIndex: false});
我有一个架构,类似:
var materialSchema = new Schema({
bookID: {type: String, required: true},
active: Boolean,
name: {type: String, required: true},
stockLength: {type: Number, required: true}
});
module.exports = mongoose.model('material', materialSchema);
当我创建新材料并将其添加到数据库时,将自动为其分配通常的_id
-这是我要维护的行为。但是,我也希望bookID
是一个唯一的,自动递增的索引。这是用于物理架子存储,而不是用于查询或类似的东西。
我希望bookID
通过以下方式递增:
A-001
A-002
A-003
...
A-098
A-099
A-100
B-001
...
B-100
...
Z-001
...
Z-100
如果上述模式不清楚,则该模式始于A-001
,最后终止于Z-100
。每个字母从001
到100
,然后再移动到下一个字母。每个新集合条目只是该模式中的下一个ID。到达终点的可能性不大,但是到达终点时,我们将越过那座桥梁。
我只使用默认的_id
进行索引,却不知道如何制作此模式。
感谢您的见解!
编辑#1
到目前为止,我想出的最好的解决方案是有一个单独的.txt
文件,其中列出了所有ID。创建每个新对象时,将下一个ID从文件顶部弹出(...移位)。这还可能具有额外的好处,即以后可以轻松添加其他ID。这可能是我采用的方法,但是我仍然对上面要求的猫鼬解决方案感兴趣。
编辑#2
所以我认为我要使用的解决方案有些不同。基本上,findOne
按bookID
降序排列。然后使用返回的值设置下一个。
Material.findOne()
.sort({bookID : -1})
.exec((err, mat) => {
if(err) {
// Send error
}else if(!mat) {
// First bookID
}else {
// Indexes exist...
let nextId = getNextID(mat.bookID);
// ...
}
});
仍然很容易修改getNextID()
以在将来添加新的/不同的ID(如果/当到达“ Z100”时)
再次感谢!
答案 0 :(得分:0)
好吧,所以要在 Edit#2 上进行一些扩展,我提出了以下解决方案。
在模型(模式)文件中,我们添加了一个schema pre()
middleware,它在保存发生之前在调用.save()
时执行:
// An arrow function will not work on this guy, if you want to use the "this" keyword
materialSchema.pre('save', function(next) {
this.model('material').findOne() // Don't forget the .model(...) bit!
.sort({bookID : -1}) // All I need is the highest (i.e. most recent) bookID
.select('bookID') // Ditto above (not really necessary)
.exec((err, result) => {
if(err) {
return next(err); // Oopsies, an error!
}else if(!result) {
this.bookID = 'A-001'; // The case when collection is empty
}else {
this.bookID = getNextID(result.bookID); // Otherwise, increment ID
}
next(); // Don't forget this sucker! This is how you save
});
});
就是这样!它不是直接来自Mongoose的内置解决方案,但可以解决问题。
仅出于完整性考虑,getNextID
函数如下所示:
function getNextID(curID) {
let letter = curID.split('-')[0];
let number = parseInt(curID.split('-')[1]);
if(number >= 100) { // Increase the letter and reset the number
letter = String.fromCharCode(letter.charCodeAt(0) + 1)
number = '001';
}else { // Only increase the number
number = ('' + (number + 1)).padStart(3, '0'); // Makes sure the numbers are always 3 digits long
}
return `${letter}-${number}`;
}
现在就做花花公子。直到我们到达Z100
。但是,如果有的话,我会过桥。没什么大不了的。
并且您无需执行任何特殊操作即可使用它。只需照常保存一个新文档,它就会自动触发:
new Material({
// New material properties
}).save((err, mat) => {
// Handle errors and returns ...
});