【问题标题】:Multitable relationship in bookshelf.jsbookshelf.js 中的多表关系
【发布时间】:2017-05-19 10:56:31
【问题描述】:

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

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 => {
    ...
  })
})

任何帮助将不胜感激!

【问题讨论】:

    标签: javascript node.js postgresql orm bookshelf.js


    【解决方案1】:

    在同一个问题上苦苦挣扎了一段时间后,这是我得到的最接近可用解决方案的方法。

    无需对您描述的模型进行任何修改(除了从User 模型中删除rights 关系),您可以这样做:

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

    我发现这更适合我的用例,因为我将始终拥有可用的用户角色以及其中的角色权限。

    类似这样的:

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

    如果您确实想要用户从所有用户角色中组合的所有权限,您可以使用 Bookshelf 的虚拟插件并创建一个虚拟行。

    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'));
      })
    })
    

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

    bookshelf.plugin(['virtuals']);
    

    这不是最优雅的解决方案,但如果你想用书架做所有事情,就是这样。每当书架让我失望时,我都会使用knex(这种情况经常发生)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-27
      • 2018-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多