【问题标题】:Manually distribute unique string identifiers to mongoDB records with mongoose and checking for duplicates使用 mongoose 手动将唯一字符串标识符分配给 mongoDB 记录并检查重复项
【发布时间】:2018-11-18 23:02:11
【问题描述】:

我正在尝试在 MEAN 堆栈中开发一个系统,该系统应包含存储在我的数据库中的卡片模型。这个模型应该有两个唯一的字段,对象 ID 和卡代码,这将是一个长度为 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:发布创建/

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

但这些似乎都不起作用,循环总是永远存在。我对节点后端比较陌生,我觉得我错过了一些东西。有谁知道我如何从异步回调中打破外循环?甚至是避免重复的替代方法?如有任何帮助,我将不胜感激!

【问题讨论】:

    标签: javascript node.js mongodb asynchronous mongoose


    【解决方案1】:

    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()
    
      // ...
    })
    

    请注意我添加的所有asyncawait

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-02
      • 2013-05-11
      相关资源
      最近更新 更多