2017-09-21 13 views
0

"products"라는 MongoDB 컬렉션 인 Sails.js 모델이 있습니다. 모델에서 'YYMMDD-count` 형식으로'170921-00001 '과 같은 고유 한 productId를 생성하는 beforeCreate() 후크가 있습니다. 여기서 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

이것은 워터 라인으로 해결하기가 어렵습니다. productId에 대한이 컨벤션이 아직 코드에 너무 많이 삽입되어 있지 않다면, 너무 많은 것을 처리하기 전에 변경하는 것이 가장 현명한 방법 일 수 있습니다.

나는 내 전화 코드에서 비슷한 문제가 있지만, 단 한 번의 호출로 배수를 생성하지 않는 모델 - 우연히도 "충돌"을 방지하기 위해 나는 전에 trycatch을 사용하여 다음을 작성합니다. catch 블록. 많은 제품이 호출 모두가 자신의 beforeCreate 실행을 만들

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(); 
     }); 
    } 
}; 

경우에도 추가되기 전에 :

그러나 여기 어쩌면 당신의 Product.js 파일에 라이브 날짜 계산을 저장할 수있을 것입니다 ... 다른 솔루션입니다 데이터베이스 (따라서 동일한 값을 얻으려면 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를 생성합니다.