Reputation: 165
The association is defined as follows:
Person.hasMany(Person, {
as: 'Parents',
through: models.Person_Parent
});
It is clear how to get all parents of an instance:
person.getParents().success(..)
But how to access the child objects of a parent?
Upvotes: 1
Views: 1173
Reputation: 382582
Minimal working example on sequelize 6.14.0
In this example I have a user follows use relationship, and I show how to get both:
The key hard step is defining the many to many both ways at:
User.belongsToMany(User, { through: 'UserFollowUser', as: 'Follows', foreignKey: 'UserId' });
User.belongsToMany(User, { through: 'UserFollowUser', as: 'Followed', foreignKey: 'FollowId' });
main.js
const assert = require('assert')
const path = require('path')
const { DataTypes, Sequelize } = require('sequelize')
let sequelize
if (process.argv[2] === 'p') {
sequelize = new Sequelize('tmp', undefined, undefined, {
dialect: 'postgres',
host: '/var/run/postgresql',
})
} else {
sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.sqlite',
})
}
function assertEqual(rows, rowsExpect) {
assert.strictEqual(rows.length, rowsExpect.length)
for (let i = 0; i < rows.length; i++) {
let row = rows[i]
let rowExpect = rowsExpect[i]
for (let key in rowExpect) {
assert.strictEqual(row[key], rowExpect[key])
}
}
}
;(async () => {
// Create the tables.
const User = sequelize.define('User', {
username: { type: DataTypes.STRING },
}, {});
User.belongsToMany(User, { through: 'UserFollowUser', as: 'Follows', foreignKey: 'UserId' });
// This is ony needed for the function followed. "foreignKey" could be removed otherwise.
User.belongsToMany(User, { through: 'UserFollowUser', as: 'Followed', foreignKey: 'FollowId' });
await sequelize.sync({ force: true });
// Create some users.
const user0 = await User.create({ username: 'user0' })
const user1 = await User.create({ username: 'user1' })
const user2 = await User.create({ username: 'user2' })
const user3 = await User.create({ username: 'user3' })
// Make user0 follow user1 and user2
await user0.addFollows([user1, user2])
// Make user2 and user3 follow user0
await user2.addFollow(user0)
await user3.addFollow(user0)
let rows
// Get users followed by an user by username.
async function followed(username, opts={}) {
return User.findAll(Object.assign({
include: [{
model: User,
as: 'Followed',
attributes: [],
through: { attributes: [] },
where: { username },
}],
// Required for limit to work.
subQuery: false,
order: [['username', 'ASC']]
}, opts))
}
rows = await followed('user0')
assertEqual(rows, [
{ username: 'user1'},
{ username: 'user2'},
])
rows = await followed('user0', { limit: 1 })
assertEqual(rows, [
{ username: 'user1'},
])
rows = await followed('user0', { order: [['username', 'DESC']] })
assertEqual(rows, [
{ username: 'user2'},
{ username: 'user1'},
])
// Now the inverse: find users that follow a given user by username.
async function following(username, opts={}) {
return User.findAll(
Object.assign({
include: [{
model: User,
as: 'Follows',
where: { username },
attributes: [],
through: { attributes: [] }
}],
// Required for limit to work.
subQuery: false,
order: [['username', 'ASC']],
}, opts)
)
}
assertEqual(await following('user0'), [
{ username: 'user2' },
{ username: 'user3' },
])
assertEqual(await following('user0', { order: [['username', 'DESC']] }), [
{ username: 'user3' },
{ username: 'user2' },
])
assertEqual(await following('user0', { limit: 1 }), [
{ username: 'user2' },
])
assertEqual(await following('user0', { limit: 1, order: [['username', 'DESC']] }), [
{ username: 'user3' },
])
assertEqual(await following('user1'), [
{ username: 'user0' },
])
assertEqual(await following('user2'), [
{ username: 'user0' },
])
assertEqual(await following('user3'), [])
})().finally(() => { return sequelize.close() });
package.json
{
"name": "tmp",
"private": true,
"version": "1.0.0",
"dependencies": {
"pg": "8.5.1",
"pg-hstore": "2.3.3",
"sequelize": "6.14.0",
"sql-formatter": "4.0.2",
"sqlite3": "5.0.2"
}
}
Tested on Ubuntu 22.04, PostgreSQL 14.3.
Bibliography:
Upvotes: 0
Reputation: 28778
You need to set up the reverse association as well
Person.hasMany(Person, {
as: 'Children',
through: models.Person_Parent
});
Upvotes: 1