Waterline手动设置主键仍报错:无法找到user模型主键
问题:Waterline模型手动指定主键仍报错"Could not find a primary key attribute"
我使用waterline: "^0.13.1-9"搭配Express开发,定义了如下User模型,已经设置autoPK: false并手动指定id为主键,但初始化Waterline时却抛出找不到主键的错误。
模型代码:
var Waterline = require('Waterline'); var bcrypt = require('bcrypt'); var User = Waterline.Collection.extend({ identity: 'user', datastore: 'myMongo', autoPK: false, attributes: { id: { type: 'integer', autoIncrement: true, primaryKey: true }, email: { type: 'string', email: true, required: true, unique: true }, username: { type: 'string', required: true, }, image: { type: 'string' }, password: { type: 'string', required: true }, mobNo: { type: 'string', required: true }, aadharNo: { type: 'string', required: true }, toJSON: function () { var obj = this.toObject(); delete obj.password; return obj; } }, beforeCreate: function (values, next) { var bcrypt = require('bcrypt'); bcrypt.genSalt(10, function (err, salt) { if (err) return next(err); bcrypt.hash(values.password, salt, function (err, hash) { if (err) return next(err); values.password = hash; next(); }); }); } }); module.exports = User;
报错信息:
userError: Could not find a primary key attribute on the model `user`. All models must contain an attribute that acts as the primary key and is guaranteed to be unique. at normalizeCollection (C:\Users\shriko\WebstormProjects\baclasses\node_modules\waterline-schema\lib\waterline-schema\schema.js:85:44) at arrayEach (C:\Users\shriko\WebstormProjects\baclasses\node_modules\@sailshq\lodash\lib\index.js:1439:13) at Function.<anonymous> (C:\Users\shriko\WebstormProjects\baclasses\node_modules\@sailshq\lodash\lib\index.js:3500:13) at schemaBuilder (C:\Users\shriko\WebstormProjects\baclasses\node_modules\waterline-schema\lib\waterline-schema\schema.js:34:5) at new WaterlineSchema (C:\Users\shriko\WebstormProjects\balajiclasses\node_modules\waterline-schema\lib\waterline-schema.js:36:12) at Object.initialize (C:\Users\shriko\WebstormProjects\baclasses\node_modules\waterline\lib\waterline.js:581:26) at Object.<anonymous> (C:\Users\shriko\WebstormProjects\baclasses\bin\www:32:18) at Module._compile (module.js:635:30) at Object.Module._extensions..js (module.js:646:10) at Module.load (module.js:554:32) at tryModuleLoad (module.js:497:12) at Function.Module._load (module.js:489:3) at Function.Module.runMain (module.js:676:10) at startup (bootstrap_node.js:187:16) at bootstrap_node.js:608:3
请问还需要配置什么才能正确创建主键?
解决方案
这个问题出在Waterline 0.13.x版本的schema验证逻辑上——虽然你在id属性里标记了primaryKey: true,但仅靠这个配置,当前版本的waterline-schema并没有正确识别出主键字段。需要额外在模型的顶层配置中明确指定主键字段名。
步骤1:修改模型配置,添加顶层primaryKey字段
在你的User模型中,除了autoPK: false,再添加一行primaryKey: 'id',明确告诉Waterline哪个字段是主键。修改后的模型代码如下:
var Waterline = require('Waterline'); var bcrypt = require('bcrypt'); var User = Waterline.Collection.extend({ identity: 'user', datastore: 'myMongo', autoPK: false, primaryKey: 'id', // 新增这一行,指定主键字段名 attributes: { id: { type: 'integer', autoIncrement: true }, // 这里可以保留primaryKey: true,也可以去掉 email: { type: 'string', email: true, required: true, unique: true }, username: { type: 'string', required: true, }, image: { type: 'string' }, password: { type: 'string', required: true }, mobNo: { type: 'string', required: true }, aadharNo: { type: 'string', required: true }, toJSON: function () { var obj = this.toObject(); delete obj.password; return obj; } }, beforeCreate: function (values, next) { // 去掉重复的bcrypt引入,顶部已经加载过了 bcrypt.genSalt(10, function (err, salt) { if (err) return next(err); bcrypt.hash(values.password, salt, function (err, hash) { if (err) return next(err); values.password = hash; next(); }); }); } }); module.exports = User;
步骤2:注意MongoDB的自增主键限制
另外要提醒你:MongoDB本身并不原生支持整数类型的自增主键。你当前设置的autoIncrement: true在MongoDB适配器中可能不会生效,需要手动实现自增逻辑。比如可以在beforeCreate钩子中查询当前最大的id值,加1后赋值给新用户的id:
beforeCreate: function (values, next) { // 查询当前最大id User.find({}).sort({id: 'desc'}).limit(1).exec(function(err, maxUser) { if (err) return next(err); values.id = maxUser.length ? maxUser[0].id + 1 : 1; // 处理密码加密 bcrypt.genSalt(10, function (err, salt) { if (err) return next(err); bcrypt.hash(values.password, salt, function (err, hash) { if (err) return next(err); values.password = hash; next(); }); }); }); }
这样修改后,Waterline就能正确识别主键,同时也能实现MongoDB中整数主键的自增功能。
内容的提问来源于stack exchange,提问作者Shrikshel
相关产品推荐
相关产品推荐

