在Sequelize中像Web应用程序一样在Twitter中进行多对多自我参考 [英] Many to many self reference in Sequelize in twitter like web-app
问题描述
我正在尝试构建一个博客网络应用程序,作为一种特别了解ORM和Sequelize的技能.我很容易地在帖子和评论与用户和帖子之间建立关系.那里没有问题.当我尝试将用户链接为关注者并将用户链接到用户时,恐怖开始了.我也希望能够跟随自己.
I'm trying to build a blog web-application as an excercise to understand ORM and Sequelize in particular. I managed quite easily to form relations between posts and comments and users and posts. No problems there. The horror begins when I try to link users to users as followers and users to users as followeds. I also want it to be possible to follow yourself.
我尝试过这样的事情:
const User = sequelize.define('user', {
firstName: {
type: Sequelize.STRING
},
lastName: {
type: Sequelize.STRING
},
email: {
type: Sequelize.STRING
},
password: {
type: Sequelize.STRING
},
activated: {
type: Sequelize.BOOLEAN
}
})
User.belongsToMany(User, {as: "Follower", foreignKey: "FollowerId", through: "Follower_Followeds"})
User.belongsToMany(User, {as: "Followed", foreignKey: "FollowedId", through: "Follower_Followeds"})
并设置关系:
app.post("/followhandler", function(req, res) {
let userId = req.session.userId
let followId = req.body.followId
User.findById(userId)
.then( currentUser => {
User.findById(followId)
.then( follows => {
currentUser.addUser(follows)
})
})
.catch(e => console.log(e))
})
但是Follower_Followeds表将不会更新.我还尝试通过创建单独的表并手动添加关系来跳过Sequelize的许多实现:
But the Follower_Followeds table will simply not get updated. I've also tried to skip the many to many implementation of Sequelize by creating a separate table and adding the relations manually:
const FollowerFollowed = sequelize.define('followerFollowed', {
followedId: {
type: Sequelize.INTEGER
},
followerId: {
type: Sequelize.INTEGER
}
})
//define Users
const User = sequelize.define('user', {
firstName: {
type: Sequelize.STRING
},
lastName: {
type: Sequelize.STRING
},
email: {
type: Sequelize.STRING
},
password: {
type: Sequelize.STRING
},
activated: {
type: Sequelize.BOOLEAN
}
})
处理程序:
app.post("/followhandler", function(req, res) {
let userId = req.session.userId
let followId = req.body.followId
FollowerFollowed.create( {
followerId: userId,
followedId: followId
})
.then( rel => console.log(rel))
.catch(e => console.log(e))
})
但是在这种情况下,我收到以下错误消息:
But I'm getting the following error in this case:
TypeError:val.replace不是函数在Object.SqlString.escape(/home/piepongwong/Documents/NYCDA/blog/node_modules/sequelize/lib/sql-string.js:61:15)在Object.escape(/home/piepongwong/Documents/NYCDA/blog/node_modules/sequelize/lib/dialects/abstract/query-generator.js:978:22)在Object.insertQuery(/home/piepongwong/Documents/NYCDA/blog/node_modules/sequelize/lib/dialects/abstract/query-generator.js:299:28)在QueryInterface.insert(/home/piepongwong/Documents/NYCDA/blog/node_modules/sequelize/lib/query-interface.js:497:33)在 .(/home/piepongwong/Documents/NYCDA/blog/node_modules/sequelize/lib/instance.js:679:56)在tryCatcher(/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/util.js:16:23)在Promise._settlePromiseFromHandler(/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/promise.js:510:31)在Promise._settlePromise(/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/promise.js:567:18)在Promise._settlePromise0(/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/promise.js:612:10)在Promise._settlePromises(/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/promise.js:691:18)在Async._drainQueue(/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/async.js:133:16)在Async._drainQueues(/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/async.js:143:10)在Instant.Async.drainQueues(/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/async.js:17:14)在runCallback(timers.js:649:20)在tryOnImmediate(timers.js:622:5)在processImmediate [as _immediateCallback](timers.js:594:5)TypeError:val.replace不是一个函数在Object.SqlString.escape(/home/piepongwong/Documents/NYCDA/blog/node_modules/sequelize/lib/sql-string.js:61:15)在Object.escape(/home/piepongwong/Documents/NYCDA/blog/node_modules/sequelize/lib/dialects/abstract/query-generator.js:978:22)在Object.insertQuery(/home/piepongwong/Documents/NYCDA/blog/node_modules/sequelize/lib/dialects/abstract/query-generator.js:299:28)在QueryInterface.insert(/home/piepongwong/Documents/NYCDA/blog/node_modules/sequelize/lib/query-interface.js:497:33)在 .(/home/piepongwong/Documents/NYCDA/blog/node_modules/sequelize/lib/instance.js:679:56)在tryCatcher(/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/util.js:16:23)在Promise._settlePromiseFromHandler(/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/promise.js:510:31)在Promise._settlePromise(/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/promise.js:567:18)在Promise._settlePromise0(/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/promise.js:612:10)在Promise._settlePromises(/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/promise.js:691:18)在Async._drainQueue(/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/async.js:133:16)在Async._drainQueues(/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/async.js:143:10)在Instant.Async.drainQueues(/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/async.js:17:14)在runCallback(timers.js:649:20)在tryOnImmediate(timers.js:622:5)在processImmediate [as _immediateCallback](timers.js:594:5)
TypeError: val.replace is not a function at Object.SqlString.escape (/home/piepongwong/Documents/NYCDA/blog/node_modules/sequelize/lib/sql-string.js:61:15) at Object.escape (/home/piepongwong/Documents/NYCDA/blog/node_modules/sequelize/lib/dialects/abstract/query-generator.js:978:22) at Object.insertQuery (/home/piepongwong/Documents/NYCDA/blog/node_modules/sequelize/lib/dialects/abstract/query-generator.js:299:28) at QueryInterface.insert (/home/piepongwong/Documents/NYCDA/blog/node_modules/sequelize/lib/query-interface.js:497:33) at . (/home/piepongwong/Documents/NYCDA/blog/node_modules/sequelize/lib/instance.js:679:56) at tryCatcher (/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/util.js:16:23) at Promise._settlePromiseFromHandler (/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/promise.js:510:31) at Promise._settlePromise (/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/promise.js:567:18) at Promise._settlePromise0 (/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/promise.js:612:10) at Promise._settlePromises (/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/promise.js:691:18) at Async._drainQueue (/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/async.js:133:16) at Async._drainQueues (/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/async.js:143:10) at Immediate.Async.drainQueues (/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/async.js:17:14) at runCallback (timers.js:649:20) at tryOnImmediate (timers.js:622:5) at processImmediate [as _immediateCallback] (timers.js:594:5) TypeError: val.replace is not a function at Object.SqlString.escape (/home/piepongwong/Documents/NYCDA/blog/node_modules/sequelize/lib/sql-string.js:61:15) at Object.escape (/home/piepongwong/Documents/NYCDA/blog/node_modules/sequelize/lib/dialects/abstract/query-generator.js:978:22) at Object.insertQuery (/home/piepongwong/Documents/NYCDA/blog/node_modules/sequelize/lib/dialects/abstract/query-generator.js:299:28) at QueryInterface.insert (/home/piepongwong/Documents/NYCDA/blog/node_modules/sequelize/lib/query-interface.js:497:33) at . (/home/piepongwong/Documents/NYCDA/blog/node_modules/sequelize/lib/instance.js:679:56) at tryCatcher (/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/util.js:16:23) at Promise._settlePromiseFromHandler (/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/promise.js:510:31) at Promise._settlePromise (/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/promise.js:567:18) at Promise._settlePromise0 (/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/promise.js:612:10) at Promise._settlePromises (/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/promise.js:691:18) at Async._drainQueue (/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/async.js:133:16) at Async._drainQueues (/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/async.js:143:10) at Immediate.Async.drainQueues (/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/async.js:17:14) at runCallback (timers.js:649:20) at tryOnImmediate (timers.js:622:5) at processImmediate [as _immediateCallback] (timers.js:594:5)
推荐答案
创建M:M关联时,请使用 as:'Follower'
和 as:'Followed'代码>属性.它影响您可以在用户之间添加/设置/删除关联的方式.现在,将关注的用户添加到其他用户的方法称为
addFollowed
,其使用方式与您完全相同.
When you create the M:M association you use as: 'Follower'
and as: 'Followed'
attributes. It influences the way you can add/set/delete associations between users. Method to add followed user to other user is now called addFollowed
and would be used in exactly the same way you did it.
User.findById(userId).then( currentUser => {
User.findById(followId).then( follows => {
currentUser.addFollowed(follows); // notice the difference here
});
});
如果要向指定用户添加关注者,则会发生相同的情况-那么您将使用 addFollower
方法.
The same occurs if you want to add follower to given user - then you would use addFollower
method.
此外,在第二种解决方案中,您在创建关联模型时犯了一个错误.在 User
模型中,您已通过外键 FollowerId
和 FollowedId
定义了关联,但是在 FollowerFolloweds
定义中创建了 followerId
和 followedId
,因此这两个不匹配-您需要保持名称一致.
Moreover, in your second solution you have made a mistake while creating the associating Model. In the User
model you have defined associations via foreign keys FollowerId
and FollowedId
, however in the FollowerFolloweds
definition you have created followerId
and followedId
, so those two do not match each other - you need to keep the names consistent.
编辑
根据 belongsToMany
关系中的文档, as
属性应命名为复数,因此在您的情况下,应将这些命名为:'Followers'
和如:'Followeds'
(第二个似乎有点奇怪).Sequelize将这些值本身单数化,但是您可以使用对象自己定义为:{单数:'Follower',复数:'Followers'}
According to the documentation in the belongsToMany
relation, the as
attribute should be named as plural, so in your case you should name those as: 'Followers'
and as: 'Followeds'
(the second one seems a little strange). Sequelize singularizes those values itself, however you can define it by yourself using object as: { singular: 'Follower', plural: 'Followers' }
此关联的别名.如果提供字符串,则应为复数,并且将使用node.inflection 进行单数化.如果要自己控制单数版本,请为对象提供复数和单数键.
The alias of this association. If you provide a string, it should be plural, and will be singularized using node.inflection. If you want to control the singular version yourself, provide an object with plural and singular keys.
这篇关于在Sequelize中像Web应用程序一样在Twitter中进行多对多自我参考的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!