2017-09-21 43 views
0

我有一個名爲「products」的Sails.js模型,它是一個MongoDB集合。在模型中,我有一個beforeCreate()掛鉤,它生成一個唯一的productId,如'YYMMDD-count`格式的'170921-00001',其中count是當天創建的記錄編號。這是我的模型看起來像:Sails.js中的數據庫調用beforeCreate()模型掛鉤導致驗證錯誤

module.exports = { 

    attributes: { 
     name: { type: 'string', required: true }, 
     productId: { type: 'string', unique: true } 
    }, 


    beforeCreate: function(values, next) { 

     var moment = require('moment'); 

     // Generate the productId 
     Products.count({ 
      createdAt: { 
       '>=': moment().format('YYYY-MM-DD'), 
       '<': moment(moment().format('YYYY-MM-DD')).add(1, 'days').format('YYYY-MM-DD') 
      } 
     }).exec(function(error, productCount) { 

      if (error) { 
       throw error; 
      } 

      var count = '', 
       totalPlaces = 5 - productCount.toString().length; 
      while (totalPlaces > 0) { 
       count = count + '0'; 
       totalPlaces--; 
      } 

      values.productId = moment().format('YYMMDD') + '-' + (count + productCount); 

      next(); 
     }); 
    } 
}; 

的問題是,該休息的時候我想多產品插入到集合在一個單一的數據庫調用。我得到以下錯誤:

debug: Error (E_VALIDATION) :: 1 attribute is invalid 
MongoError: E11000 duplicate key error index: my-app.products.$productId_1 dup key: { : "170921-00002" } 
    at Function.MongoError.create (/Users/Nag/Code/my-app/web-service/node_modules/sails-mongo/node_modules/mongodb-core/lib/error.js:31:11) 
    at toError (/Users/Nag/Code/my-app/web-service/node_modules/sails-mongo/node_modules/mongodb/lib/utils.js:114:22) 
    at /Users/Nag/Code/my-app/web-service/node_modules/sails-mongo/node_modules/mongodb/lib/collection.js:658:23 
    at handleCallback (/Users/Nag/Code/my-app/web-service/node_modules/sails-mongo/node_modules/mongodb/lib/utils.js:95:56) 
    at resultHandler (/Users/Nag/Code/my-app/web-service/node_modules/sails-mongo/node_modules/mongodb/lib/bulk/ordered.js:421:14) 
    at /Users/Nag/Code/my-app/web-service/node_modules/sails-mongo/node_modules/mongodb-core/lib/connection/pool.js:455:18 
    at /Users/Nag/Code/my-app/web-service/node_modules/async-listener/glue.js:188:31 
    at _combinedTickCallback (internal/process/next_tick.js:73:7) 
    at process._tickDomainCallback (internal/process/next_tick.js:128:9) 
    at process.fallback (/Users/Nag/Code/my-app/web-service/node_modules/async-listener/index.js:529:15) 

Invalid attributes sent to undefined: 
• productId 
    • A record with that `productId` already exists (`170921-00002`). 

當我插入一條記錄,它工作正常,但是當我插入多條記錄,第一個記錄被插入,但以後每記錄生成該錯誤。是否因爲在鉤子計算出productId之前插入文檔之前插入文檔?我該如何解決這個問題?

+0

您使用的是什麼版本的Sails?你可以發佈你用來創建記錄的代碼嗎? – sgress454

回答

0

這是用Waterline解決的一個相當困難的問題。如果productId的這個約定不是太嵌入你的代碼中,最明智的可能就是在它周圍建立太多之前就改變它。

我有一個類似的問題在我的代碼,但是,我從來沒有在一個單一的呼叫建立的倍數模型 - 謹防巧合「衝突」我只是用在創建之前trycatch並重新運行創造catch塊。

但這裏的另一種解決方案......也許這將是可能存儲活一天算在你的Product.js文件:

var day = new Date(); 
var daycount = 0; 

module.exports = { 

    attributes: { 
     name: { type: 'string', required: true }, 
     productId: { type: 'string', unique: true } 
    }, 
    beforeCreate: function(values, next) { 
     var moment = require('moment'); 
     // Generate the productId 
     Products.count({ 
      createdAt: { 
       '>=': moment().format('YYYY-MM-DD'), 
       '<': moment(moment().format('YYYY-MM-DD')).add(1, 'days').format('YYYY-MM-DD') 
      } 
     }).exec(function(error, productCount) { 
      if (error) { 
       throw error; 
      } 

      // stop here to check your day and count variables... 
      var today = new Date(); 
      if (productCount === 0) { // none created yet today 
       day = today; 
       daycount = 0; 
      } else if (daycount === 0) { // must have started the app with records in db 
       daycount = productCount; 
      } 
      if (day < today && day.getDate() < today.getDate()) { // new day 
       day = today; 
       daycount = 0; 
      } 
      productCount = Math.max(productCount, daycount++); // notice the increment 
      // now proceed as before... 

      var count = '', 
       totalPlaces = 5 - productCount.toString().length; 
      while (totalPlaces > 0) { 
       count = count + '0'; 
       totalPlaces--; 
      } 
      values.productId = moment().format('YYMMDD') + '-' + (count + productCount); 
      next(); 
     }); 
    } 
}; 

即使許多產品創造通話都有自己beforeCreate運行被添加到前數據庫(因此得到相同的productCount),daycountday變量應該在內存中保存並逐一更新。

即使這樣做,它感覺岌岌可危 - 我會認真考慮重組您的數據,而不是採取這種方法!

0

當您向api發送數據時,您是否建立了產品名稱?

name: { type: 'string', required: true } <= Here, the name is required from client to api. 
+0

你的問題應該在評論中。不是問題的答案。 –

0

你應該更新方法之前,讓獨特的價值觀:

values.productId = moment().format('YYMMDD') + '-' + (count + productCount);

代碼的該行可能是:

values.productId = moment().format('YYMMDD') + '-' + (count + productCount)+ Math.random();

它產生總是唯一的ID。