如何在书架中建立自引用多对多关系
Posted
技术标签:
【中文标题】如何在书架中建立自引用多对多关系【英文标题】:How to do a Self-Referencing Many-to-Many Relationship in Bookshelf 【发布时间】:2016-06-05 16:09:19 【问题描述】:我正在尝试在Bookshelf.Js 中找出最清晰和“正确”的方式,即为用户模型设置多对多关系以构建存在于许多社交应用。不过,Bookshelf 中的文档让我陷入了困境。
我可以看到两种可能的方法:1) 单独使用 belongsToMany()
,或 2) 将 belongsToMany()
与 throught()
一起使用。两者都没有为我工作,但让我首先向您展示我正在为(1)做什么。我从这个模型设置开始:
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');
,
);
为了匹配,我有一个 knex 迁移,它添加了一个 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_
道具,看起来好像在这里设置了某种关系,但我不清楚它们是什么,我不确定为什么 @987654332 @ 字段返回为空。
如果有人可以在这里直截了当或以任何方式阐明情况,我将不胜感激。
【问题讨论】:
【参考方案1】:我想那些 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 ]
【讨论】:
以上是关于如何在书架中建立自引用多对多关系的主要内容,如果未能解决你的问题,请参考以下文章