Files
linux-kernel-module-cheat/rootfs_overlay/lkmc/nodejs/sequelize/association_many_to_many.js
2021-06-17 17:17:47 +01:00

162 lines
4.7 KiB
JavaScript
Executable File

#!/usr/bin/env node
// https://stackoverflow.com/questions/22958683/how-to-implement-many-to-many-association-in-sequelize/67973948#67973948
const assert = require('assert');
const path = require('path');
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
});
(async () => {
// Create the tables.
const User = sequelize.define('User', {
name: { type: DataTypes.STRING },
}, {});
const Post = sequelize.define('Post', {
body: { type: DataTypes.STRING },
}, {});
// UserLikesPost is the name of the relation table.
// Sequelize creates it automatically for us.
// On SQLite that table looks like this:
// CREATE TABLE `UserLikesPost` (
// `createdAt` DATETIME NOT NULL,
// `updatedAt` DATETIME NOT NULL,
// `UserId` INTEGER NOT NULL REFERENCES `Users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
// `PostId` INTEGER NOT NULL REFERENCES `Posts` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
// PRIMARY KEY (`UserId`, `PostId`)
// );
User.belongsToMany(Post, {through: 'UserLikesPost'});
Post.belongsToMany(User, {through: 'UserLikesPost'});
await sequelize.sync({force: true});
// Create some users and likes.
const user0 = await User.create({name: 'user0'})
const user1 = await User.create({name: 'user1'})
const user2 = await User.create({name: 'user2'})
const post0 = await Post.create({body: 'post0'});
const post1 = await Post.create({body: 'post1'});
const post2 = await Post.create({body: 'post2'});
// Autogenerated add* methods
// Make user0 like post0
await user0.addPost(post0)
// Also works.
//await user0.addPost(post0.id)
// Make user0 and user2 like post1
await post1.addUsers([user0, user2])
// Autogenerated get* methods
// Get likes by a user.
const user0Likes = await user0.getPosts({order: [['body', 'ASC']]})
assert(user0Likes[0].body === 'post0');
assert(user0Likes[1].body === 'post1');
assert(user0Likes.length === 2);
const user1Likes = await user1.getPosts({order: [['body', 'ASC']]})
assert(user1Likes.length === 0);
const user2Likes = await user2.getPosts({order: [['body', 'ASC']]})
assert(user2Likes[0].body === 'post1');
assert(user2Likes.length === 1);
// Same as get but with the user ID instead of the model object.
{
const user0Likes = await Post.findAll({
include: [{
model: User,
where: {id: user0.id},
}],
order: [['body', 'ASC']],
})
assert(user0Likes[0].body === 'post0');
assert(user0Likes[1].body === 'post1');
assert(user0Likes.length === 2);
}
// Yet another way that can be more useful in nested includes.
{
const user0Likes = (await User.findOne({
where: {id: user0.id},
include: [{
model: Post,
}],
order: [[Post, 'body', 'ASC']],
})).Posts
assert(user0Likes[0].body === 'post0');
assert(user0Likes[1].body === 'post1');
assert(user0Likes.length === 2);
}
// Get users that liked a given likes.
const post0Likers = await post0.getUsers({order: [['name', 'ASC']]})
assert(post0Likers[0].name === 'user0');
assert(post0Likers.length === 1);
const post1Likers = await post1.getUsers({order: [['name', 'ASC']]})
assert(post1Likers[0].name === 'user0');
assert(post1Likers[1].name === 'user2');
assert(post1Likers.length === 2);
const post2Likers = await post2.getUsers({order: [['name', 'ASC']]})
assert(post2Likers.length === 0);
// Autogenerated has* methods
// Check if user likes post.
assert( await user0.hasPost(post0))
assert( await user0.hasPost(post0.id)) // same
assert( await user0.hasPost(post1))
assert(!await user0.hasPost(post2))
// Check if post is liked by user.
assert( await post0.hasUser(user0))
assert(!await post0.hasUser(user1))
assert(!await post0.hasUser(user2))
// AND of multiple has checks at once.
assert( await user0.hasPosts([post0, post1]))
assert(!await user0.hasPosts([post0, post1, post2]))
// Autogenerated count* methods
assert(await user0.countPosts() === 2)
assert(await post0.countUsers() === 1)
// Autogenerated remove* methods
// user0 doesn't like post0 anymore.
await user0.removePost(post0)
// user0 and user 2 don't like post1 anymore.
await post1.removeUsers([user0, user2])
// Check that no-one likes anything anymore.
assert(await user0.countPosts() === 0)
assert(await post0.countUsers() === 0)
// Autogenerated create* method
// Create a new post and automatically make user0 like it.
const post3 = await user0.createPost({'body': 'post3'})
assert(await user0.hasPost(post3))
assert(await post3.hasUser(user0))
// Autogenerated set* method
// Make user0 like exactly these posts. Unlike anything else.
await user0.setPosts([post1, post2])
assert(!await user0.hasPost(post0))
assert( await user0.hasPost(post1))
assert( await user0.hasPost(post2))
assert(!await user0.hasPost(post3))
await sequelize.close();
})();