Sails.js + Waterline:通过关联进行多对多
Posted
技术标签:
【中文标题】Sails.js + Waterline:通过关联进行多对多【英文标题】:Sails.js + Waterline: Many-to-Many through association 【发布时间】:2014-11-19 09:22:06 【问题描述】:我是 Sails.js (v0.10.5) 和 Waterline ORM 的新手。我在数据库中有 3 个表:用户(id,名称),角色(id,别名)和连接表 users_roles(user_id,role_id)。重要的是不要更改数据库中的表名和字段名。我希望策略实体成为用户和角色之间的连接实体。这是一些映射代码:
//User.js
module.exports =
tableName: 'users',
autoCreatedAt: false,
autoUpdatedAt: false,
attributes:
id:
type: 'integer',
required: true
,
name:
type: 'string'
,
roles:
collection: 'role',
via: 'users',
through: 'policy'
,
//Role.js
module.exports =
tableName: "roles",
autoCreatedAt: false,
autoUpdatedAt: false,
attributes:
id:
type: 'integer',
required: true
,
alias:
type: 'string',
required: true
,
users:
collection: 'user',
via: 'roles',
through: 'policy'
//Policy.js
module.exports =
tableName: "users_roles",
tables: ['users', 'roles'],
junctionTable: true,
autoCreatedAt: false,
autoUpdatedAt: false,
attributes:
user:
columnName: 'user',
type: 'integer',
foreignKey: true,
references: 'user',
on: 'id',
via: 'role',
groupBy: 'user'
,
roles:
columnName: 'role',
type: 'integer',
foreignKey: true,
references: 'role',
on: 'id',
via: 'user',
groupBy: 'role'
但是当我尝试访问控制器中的角色属性时
User.findOne(id: 1).populate('roles').exec(function(err, user)
console.log(JSON.stringify(user.roles));
);
这会返回
[]
还有
User.findOne(id: 1).populate('roles').exec(function(err, user)
console.log(JSON.stringify(user));
);
返回
"id":1,"name":"test", "roles":[]
我检查了两次用户、角色和它们之间的关联是否存在于数据库中。我的错误是什么?
【问题讨论】:
你能把代码过去吗?确保您正在执行 User.find().populate('roles').exec(function()) @mandeep_m91 感谢您的回复!我编辑了问题(console.log 输出中有一些错误)。 你能解决这个问题吗?如果没有,您使用的是哪个底层数据库? @mandeep_m91 我已经解决了这个问题。我向 Policy 实体添加了一个 ID 字段,并将 User 和 Policy(以及 Role 和 Policy)之间的关联更改为 OneToMany。这不是我真正想要的,但它有效.. @mandeep_m91 我正在使用 postgresql 9.3 【参考方案1】:我找到了解决这个问题的方法。这不是我真正想要的,但它有效。 第一:加入实体:
//Policy.js
module.exports =
tableName: "users_roles",
autoPK: false,
attributes:
id:
type: 'integer',
primaryKey: true,
autoIncrement: true,
,
user:
columnName: 'user_id',
model: 'user'
,
role:
columnName: 'role_id',
model: 'role'
,
//tricky method to get all users for specified role_id
//or to get all roles for specified user_id
get: function(id, modificator, cb)
var fields = ['user', 'role'];
if (fields.indexOf(modificator) < 0)
cb(new Error('No such modificator in Policy.get()'), null);
var inversedField = fields[(fields.indexOf(modificator) + 1) % 2];
var condition = ;
condition[inversedField] = id;
this.find(condition).populate(modificator).exec(function(err, policies)
if (err)
cb(err, null);
return;
var result = [];
policies.forEach(function(policy)
result.push(policy[modificator]);
);
cb(null, result);
return;
);
如您所见,我将 ID 字段添加到该实体(以及 db 表 users_roles 中),所以这不是很好的解决方案。
//User.js
module.exports =
tableName: 'users',
autoPK: false,
attributes:
id:
type: 'integer',
primaryKey: true,
autoIncrement: true,
unique: true,
,
name:
type: 'string'
,
policies:
collection: 'policy',
via: 'user'
和角色实体:
//Role.js
module.exports =
tableName: 'roles',
autoPK: false,
attributes:
id:
type: 'integer',
primaryKey: true,
autoIncrement: true,
,
alias:
type: 'string',
required: true,
unique: true,
,
policies:
collection: 'policy',
via: 'role'
这就是我获取指定 user_id 的所有角色的方式:
...
id = req.session.me.id; //user_id here
Policy.get(id, 'role', function(err, roles)
var isAdmin = false;
roles.forEach(function(role)
isAdmin |= (role.id === 1);
);
if (isAdmin)
next(null);
return;
else
return res.redirect('/login');
);
...
也许它对某人有用 =)
【讨论】:
差不多 2 年后对我很有用!谢谢!以上是关于Sails.js + Waterline:通过关联进行多对多的主要内容,如果未能解决你的问题,请参考以下文章
Sails.js / Waterline - 创建不是模型上的功能
Sails.js/waterline: groupBy + count
Sails.js Waterline ORM:.findOrCreate() 没有 .populate() 方法