如何在书架中自我引用多对多关系

时间:2016-06-05 16:09:20

标签: javascript orm bookshelf.js

我试图找出最清晰明确的"正确的" Bookshelf.Js中为用户模型建立多对多关系以构建许多社交应用程序中存在的标准关注者/关注关系的方式。然而,Bookshelf中的文档让我陷入了一个循环。

我可以看到两种可能的方法:1)单独使用SideNavigationController,或2)将belongsToMany()belongsToMany()一起使用。两者都没有对我有用,但让我先告诉你我为之做的事情(1)。我从这个模型设置开始:

throught()

为了匹配我有一个knex迁移,它添加了const User = bookshelf.Model.extend({ tableName: 'users', initialize: function() { this.on('creating', this.encryptPassword); }, hasTimestamps: true, posts: function() { return this.hasMany(Posts, 'author'); }, comments: function() { return this.hasMany(Comments); }, following: function() { return this.belongsToMany(UserFollow, 'users_users', 'follower_id', 'user_id'); }, followers: function() { return this.belongsToMany(UserFollow, 'users_users', 'user_id', 'follower_id'); }, }); 表,如下所示:

users_users

然后我进行了以下测试:

exports.up = function(knex, Promise) {
  return knex.schema.createTable('users_users', (tbl) => {
    tbl.integer('user_id').references('users.id');
    tbl.integer('follower_id').references('users.id');
    tbl.unique(['user_id', 'follower_id']);  
      // This b/c I read a few places that Bookshelf might require a composite key.
  });
};

exports.down = function(knex, Promise) {
  return knex.schema.dropTable('users_users');
};

我在这里测试的确不多,因为我还没有能够得到这个,工作,但是it('User model can record a follower', (done) => { const saveUsr = (data) => { return User.forge().save(data, {transacting: transaction}); }; Promise.all([saveUsr(mockUser), saveUsr(anotherMockUser)]) .then((results) => { let usr1 = results[0]; let usr2 = results[1]; return usr2.followers().attach(usr1.id, {transacting: transaction}); }) .then((usrWithFollower) => { return usrWithFollower.fetch({ withRelated: ['followers'], transacting: transaction }); }) .then((usr) => { console.log(JSON.stringify(usr)); console.log('followers: ', usr.get('followers')); done(); }) .catch((err) => { done(err); }); }); 在最后一个承诺中的结果然后是回调如下:

JSON.stringify(user)

正如你所看到的那样,假设有这些[ { "id":1, "name":"Sally Low", "username":"sally", "email":"sally@example.org", "created_at":"2016-06-05T15:24:41.835Z", "updated_at":"2016-06-05T15:24:41.835Z", "password":"$2a$10$613tL/baML9obsRN4Yg7MeU/2RiH7oK/nFUwfpQ1GYuA15VUFrFZu", "followers": [], "_pivot_user_id":2, "_pivot_follower_id":1 } ] 道具,看起来好像已经设置了某种关系,但它们对我来说并不清楚,我不确定为什么_pivot_字段空回来。

如果有人可以让我直截了当或以任何方式阐明情况,我会非常感激。

1 个答案:

答案 0 :(得分:0)

我认为那些UserFollow模型是User别名。这不是必需的。

尝试添加Registry Plugin并将您的User模型写为:

const User = bookshelf.Model.extend({
  tableName: 'users',
  // ...
  following: function() {
    return this.belongsToMany('User', 'users_users', 'follower_id', 'user_id');
  },
  followers: function() {
    return this.belongsToMany('User', 'users_users', 'user_id', 'follower_id');
  },
});
bookshelf.model('User', User);

attach()代码可以直接使用模型,无需使用id

usr2.followers().attach(usr1);

我制作了架构的最小版本并尝试了:

new User({name: 'Bia'}).
  fetch({withRelated: 'followers'}).
  then((m) => {console.log(m.toJSON());});

这让我回来了:

{ name: 'Bia',
   id: 3,
   followers: 
    [ { id: 1, name: 'Ana', _pivot_user_id: 3, _pivot_follower_id: 1 },
      { id: 2, name: 'Mia', _pivot_user_id: 3, _pivot_follower_id: 2 } ] }