Распространение уникальных строковых идентификаторов вручную в записях mongoDB с помощью mongoose и проверка на наличие дубликатов - PullRequest
0 голосов
/ 08 июня 2018

Я пытаюсь разработать систему в стеке MEAN, которая должна содержать модель карты, хранящуюся в моей БД.Эта модель должна иметь два уникальных поля: идентификатор объекта и код карты, которые будут представлять собой буквенно-цифровую строку длиной 8 символов.Моя схема похожа на:

var cardSchema = new Schema({
  cod: {type: String, required: true, unique: true},
  titular: {type: String, required: true, index: true},
  balance: {type: Number, default: 500, min: 0, max: 500, required: true},
  lastCredited: {type: Date, default: Date.now(), required: true}
})

А потом я создавал свои объекты, такие как:

cards.js: post create /

router.post('/create', function(req, res) {
  let card = new Card()
  card.cod = Card.generateCod()
  card.credit()
  if (/^[a-zA-Z\s]+$/.test(req.body.titular)) {
    card.titular = req.body.titular.toUpperCase()
  }
  else{
    res.status(406).send('Invalid name for titular')
    return
  }
  card.save(function (err, result) {
    if(err) res.status(406).send(err)
    else res.status(200).send(result)
  })
})

Мой статический метод generateCodотвечал за распространение случайного строкового кода на карточки:

cardSchema.statics.generateCod = function(){
  let possible = "ABCDEFGHIJ0123456789"
  let cod = ''

  for (var i = 0; i < 8; i++) cod += possible.charAt(Math.floor(Math.random() * possible.length))
  return cod
}

Однако, чтобы избежать дублирования кодов, я искал какой-нибудь способ проверить, использовался ли уже сгенерированный код, а затемв положительном случае я бы сгенерировал еще один и повторил процесс, в отрицательном случае я бы просто возвратил код.Решением, которое я нашел, было отправка запроса в БД с передачей моего кода в качестве параметра и проверкой длины ответа, если длина была равна 0, это означало, что код был уникальным.Пока все хорошо, проблема в том, что мой запрос происходит асинхронно с кодом, я не могу просто использовать цикл while или for, чтобы проверить, является ли код уникальным, и разорвать цикл, когда он есть, потому что разрыв не будетработа и цикл будет продолжаться вечно.Я на самом деле пробовал это так:

while(true){
  for (var i = 0; i < 8; i++) cod += possible.charAt(Math.floor(Math.random() * possible.length))
  Card.find({cod: cod}, function(err, result) {
      if(result.length === 0) break
  })
}
return cod

Я также пробовал:

while(true){
  for (var i = 0; i < 8; i++) cod += possible.charAt(Math.floor(Math.random() * possible.length))
  Card.find({cod: cod}, function(err, result) {
      if(result.length === 0) return cod
  })
}

И даже:

let unique = false
while(!unique){
  for (var i = 0; i < 8; i++) cod += possible.charAt(Math.floor(Math.random() * possible.length))
  Card.find({cod: cod}, function(err, result) {
      if(result.length === 0) unique = true
  })
}
return cod

Но, похоже, ни один из них не работает,петля всегда идет вечно.Я относительно новичок в бэкэндах узлов и чувствую, что что-то упустил.Кто-нибудь знает, как я могу разорвать внешний цикл от асинхронного обратного вызова?Или даже альтернативный способ избежать дубликатов?Буду благодарен за любую помощь!

1 Ответ

0 голосов
/ 09 июня 2018

Mongoose имеет встроенную поддержку Promise, поэтому вы можете использовать async/await здесь:

cardSchema.statics.generateCod = async function() {
  let possible = "ABCDEFGHIJ0123456789";
  let cod = '';

  for (let i = 0; i < 8; i++) {
    cod += possible.charAt(Math.floor(Math.random() * possible.length));
  }

  let dup = await Card.findOne({cod: cod});

  if (dup) {
      return new Error("Can not generate COD");
  }

  return cod;
}

router.post('/create', async function(req, res) {
  let card = new Card()

  card.cod = await Card.generateCod()

  // ...
})

Обратите внимание на все добавленные мной async и await.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...