#mysql #reactjs #sequelize.js #associations
#javascript #node.js #База данных #многие ко многим #sequelize.js
Вопрос:
Я пытаюсь создать веб-приложение для блога в качестве упражнения для понимания ORM и Sequelize в частности. Мне удалось довольно легко сформировать отношения между сообщениями и комментариями, пользователями и сообщениями. Никаких проблем нет. Ужас начинается, когда я пытаюсь связать пользователей с пользователями как подписчиков, а пользователей с пользователями как подписчиков. Я также хочу, чтобы можно было следить за собой.
Я пробовал что-то вроде этого:
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 «многие ко многим», создав отдельную таблицу и добавив отношения вручную:
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:
Ошибка типа: 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) в немедленном.Async.drainQueues (/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/async.js:17:14) при обратном вызове (timers.js:649:20) в tryOnImmediate (timers.js: 622:5) при промежуточном процессе [как _immediateCallback] (timers.js:594:5) Ошибка типа: 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) немедленно.Async.drainQueues (/home/piepongwong/Documents/NYCDA/blog/node_modules/bluebird/js/release/async.js:17:14) в runCallback (timers.js:649:20) в tryOnImmediate (таймеры.js:622:5) в processImmediate [как _immediateCallback] (timers.js:594:5)
Ответ №1:
Когда вы создаете ассоциацию M: M, вы используете as: 'Follower'
as: 'Followed'
атрибуты и . Это влияет на то, как вы можете добавлять / устанавливать / удалять ассоциации между пользователями. Теперь вызывается метод добавления подписанного пользователя к другому пользователю addFollowed
, и он будет использоваться точно так же, как вы это делали.
User.findById(userId).then( currentUser => {
User.findById(followId).then( follows => {
currentUser.addFollowed(follows); // notice the difference here
});
});
То же самое происходит, если вы хотите добавить подписчика к данному пользователю — тогда вы должны использовать addFollower
метод.
Более того, в вашем втором решении вы допустили ошибку при создании ассоциирующей модели. В User
модели вы определили ассоциации с помощью внешних ключей FollowerId
и FollowedId
, однако в FollowerFolloweds
созданном вами определении followerId
и followedId
, поэтому эти два не совпадают друг с другом — вам необходимо поддерживать согласованность имен.
Редактировать
Согласно документации в belongsToMany
отношении, as
атрибут должен быть назван во множественном числе, поэтому в вашем случае вы должны назвать их as: 'Followers'
и as: 'Followeds'
(второе кажется немного странным). Sequelize выделяет эти значения самостоятельно, однако вы можете определить это самостоятельно, используя object as: { singular: 'Follower', plural: 'Followers' }
Псевдоним этой ассоциации. Если вы предоставляете строку, она должна быть множественной и будет выделена с помощью node.inflection . Если вы хотите самостоятельно управлять единственной версией, предоставьте объекту ключи множественного и единственного числа.