#node.js #mongodb #express #mongoose #indexing
#node.js #mongodb #экспресс #mongoose #индексирование
Вопрос:
Я инициализирую свою базу данных обычным способом:
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
для индексации и не могу понять, как создать этот шаблон.
Спасибо за любую информацию!
Правка # 1
Лучшее решение, которое я придумал на данный момент, — это создать отдельный .txt
файл со всеми идентификаторами, перечисленными по порядку. По мере создания каждого нового объекта перемещайте (… shift) следующий идентификатор с верхней части файла. Это также может иметь дополнительное преимущество в виде простого добавления дополнительных идентификаторов позже. Вероятно, я воспользуюсь таким подходом, но меня все еще интересует решение mongoose, запрошенное выше.
Правка # 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()
, чтобы добавить новые / отличающиеся идентификаторы в будущем (если / когда будет достигнут «Z100»)
Еще раз спасибо!
Ответ №1:
Хорошо, итак, чтобы немного расширить правку № 2, я предложил следующее решение.
В файл модели (схемы) мы добавляем промежуточное программное обеспечение pre()
schema , которое выполняется при .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 ...
});