You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:49:33