MongoDB и Mongoose - Создание пользовательских вторичных идентификаторов с автоматической индексацией? - PullRequest
0 голосов
/ 03 апреля 2019

Я инициализирую свою БД обычным способом:

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 со всеми идентификаторами, перечисленными по порядку. По мере создания каждого нового объекта вставляйте (... сдвигайте) следующий идентификатор в верхней части файла. Это также может иметь дополнительное преимущество, заключающееся в простом добавлении дополнительных идентификаторов на более позднем этапе. Вероятно, это будет подход, который я выберу, но я все еще заинтересован в решении мангуста, запрошенном выше.

Редактировать # 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 Ответ

0 голосов
/ 08 апреля 2019

Хорошо, поэтому, чтобы немного расширить Edit # 2 , я нашел следующее решение.

В файле модели (схемы) мы добавляем схема pre() промежуточное ПО , которое выполняется при вызове .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 ...
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...