我有一个名为“products”的Sails.js模型,它是一个MongoDB集合。在模型中,我有一个beforeCreate()
钩子,它以'YYMMDD-count`格式生成一个独特的productId,如'170921-00001',其中count是当天创建的记录号。这就是我的模型:
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 :(得分:0)
使用Waterline解决这个问题非常困难。如果productId的这个约定还没有嵌入到你的代码中,那么最明智的做法可能是在它构建太多之前进行更改。
我在我的代码中遇到了类似的问题,但是使用的模型我从来没有在一次调用中创建多个 - 为了防止巧合的“碰撞”我只使用了try
catch
在创建并重新运行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
),daycount
和day
变量应该在记忆中保存,并逐一更新。
即使这样有效,但感觉不稳定 - 我会认真考虑重组你的数据,而不是采用这种方法!
答案 1 :(得分:0)
当您向api发送数据时,您是否在确定产品名称?
name: { type: 'string', required: true } <= Here, the name is required from client to api.
答案 2 :(得分:0)
您应该在更新方法之前创建唯一值:
values.productId = moment()。format('YYMMDD')+' - '+(count + productCount);
您的代码的这一行可能是:
values.productId = moment()。format('YYMMDD')+' - '+(count + productCount)+ Math.random();
它始终生成唯一ID。