Bookshelf.js中的多重关系

我试图在node.js应用程序中使用bookshelf.js作为ORM到Postgresql来实现基于angular色的访问控制。 我有以下架构:

USERS <- USERS_ROLES -> ROLES <- ROLES_RIGHTS -> RIGHTS 

我希望能够获得用户拥有的所有权利。 在SQL中,我只是这样做:

 SELECT rights.* FROM rights INNER JOIN roles_rights ON roles_rights.right_id=rights.id INNER JOIN users_roles ON users_roles.role_id = roles_rights.role_id WHERE users_roles.user_id=1 GROUP BY rights.id 

对于Bookshelf.js来说,这是一个相对较新的问题,但是在设置关系时遇到了一些麻烦。 这是我第一次尝试:

 const User = bookshelf.Model.extend({ tableName: 'users', roles: function() { return this.belongsToMany(Role, 'users_roles', 'user_id', 'role_id') }, rights: function() { return this.belongsToMany(Right, 'users_roles', 'user_id', 'role_id') .query(qb => qb .innerJoin('roles_rights', 'roles_rights.right_id', 'rights.id') ) } }) const Role = bookshelf.Model.extend({ tableName: 'roles', rights: function() { return this.belongsToMany(Right, 'roles_rights', 'role_id', 'right_id') }, users: function() { return this.belongsToMany(User, 'users_roles', 'user_id', 'role_id') } }) const Right = bookshelf.Model.extend({ tableName: 'rights', roles: function() { return this.belongsToMany(Role, 'users_roles', 'user_id', 'role_id') } }) 

它不起作用… :-(

最终,我想使这个查询工作:

 User.where({ id: req.user.get('id') }) .fetch({ withRelated: ['rights'] }) .then(user => { ... }) }) 

任何帮助将不胜感激!

经过一段时间的同样的问题,这是最接近我得到一个可用的解决scheme。

如果不修改您所描述的模型(除了从User模型中删除rights关系),您可以这样做:

 User.where({ id: req.user.get('id') }) .fetch({ withRelated: ['roles.rights'] }) .then(user => { console.log(JSON.stringify(user)); }) }) 

我发现这对我的用例来说是一个更好的select,因为我将始终拥有可用的用户angular色和angular色的权限。

像这样的东西:

 { id: 12 roles: [ { id: 21, rights: [ { id: 11, name: 'DELETE' } ] } ] } 

如果您确实需要用户从所有用户angular色组合的所有权限,则可以使用Bookshelf的虚拟插件并创build虚拟行。

 const User = bookshelf.Model.extend({ tableName: 'users', roles: function() { return this.belongsToMany(Role, 'users_roles', 'user_id', 'role_id') }, virtuals: { rights: { get: function () { const rightsIds = new Set(); return this.related('roles').reduce((rights, group) => { return group.related('rights').reduce((rights, right) => { if (!rightsIds.has(right.id)) { rightsIds.add(right.id); rights.push(right); } return rights; }, rights); }, []); } } }, }); 

像这样使用它:

 User.where({ id: req.user.get('id') }) .fetch({ withRelated: ['roles.rights'] }) .then(user => { console.log(JSON.stringify(user.get('rights')); }) }) 

初始化书架时必须启用虚拟插件:

 bookshelf.plugin(['virtuals']); 

这不是最优雅的解决scheme,但如果你想用书架做所有事情,就是这样。 我只是在书架让我失望的时候使用knex (而且发生了很多)。