and more sequelize

This commit is contained in:
Ciro Santilli
2021-06-17 17:17:47 +01:00
parent fa0766e88f
commit 87049eb552
5 changed files with 382 additions and 6 deletions

View File

@@ -70,7 +70,7 @@ 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.
// Same as get but with the user ID instead of the model object.
{
const user0Likes = await Post.findAll({
include: [{
@@ -84,6 +84,20 @@ assert(user2Likes.length === 1);
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']]})
@@ -96,9 +110,7 @@ assert(post1Likers[1].name === 'user2');
assert(post1Likers.length === 2);
const post2Likers = await post2.getUsers({order: [['name', 'ASC']]})
assert(post1Likers[0].name === 'user0');
assert(post1Likers[1].name === 'user2');
assert(post1Likers.length === 2);
assert(post2Likers.length === 0);
// Autogenerated has* methods

View File

@@ -0,0 +1,141 @@
#!/usr/bin/env node
// Two associations between two specific models. Requires us to use alias with `as:`
// to disambiguate them.
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 },
}, {});
User.belongsToMany(Post, {through: 'UserLikesPost', as: 'likedPosts'});
Post.belongsToMany(User, {through: 'UserLikesPost', as: 'likers'});
User.belongsToMany(Post, {through: 'UserFollowsPost', as: 'followedPosts'});
Post.belongsToMany(User, {through: 'UserFollowsPost', as: 'followers'});
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
// Setup likes and follows.
await user0.addLikedPost(post0)
await post1.addLikers([user0, user2])
await user1.addFollowedPosts([post0, post1])
await post1.addFollower(user2)
// Autogenerated get* methods
// Get likes by a user.
const user0Likes = await user0.getLikedPosts({order: [['body', 'ASC']]})
assert(user0Likes[0].body === 'post0');
assert(user0Likes[1].body === 'post1');
assert(user0Likes.length === 2);
const user1Likes = await user1.getLikedPosts({order: [['body', 'ASC']]})
assert(user1Likes.length === 0);
const user2Likes = await user2.getLikedPosts({order: [['body', 'ASC']]})
assert(user2Likes[0].body === 'post1');
assert(user2Likes.length === 1);
// Get users that liked a given post.
const post0Likers = await post0.getLikers({order: [['name', 'ASC']]})
assert(post0Likers[0].name === 'user0');
assert(post0Likers.length === 1);
const post1Likers = await post1.getLikers({order: [['name', 'ASC']]})
assert(post1Likers[0].name === 'user0');
assert(post1Likers[1].name === 'user2');
assert(post1Likers.length === 2);
const post2Likers = await post2.getLikers({order: [['name', 'ASC']]})
assert(post2Likers.length === 0);
// Get follows by a user.
const user0Follows = await user0.getFollowedPosts({order: [['body', 'ASC']]})
assert(user0Follows.length === 0);
const user1Follows = await user1.getFollowedPosts({order: [['body', 'ASC']]})
assert(user1Follows[0].body === 'post0');
assert(user1Follows[1].body === 'post1');
assert(user1Follows.length === 2);
const user2Follows = await user2.getFollowedPosts({order: [['body', 'ASC']]})
assert(user2Follows[0].body === 'post1');
assert(user2Follows.length === 1);
// Get users that followed a given post.
const post0Followers = await post0.getFollowers({order: [['name', 'ASC']]})
assert(post0Followers[0].name === 'user1');
assert(post0Followers.length === 1);
const post1Followers = await post1.getFollowers({order: [['name', 'ASC']]})
assert(post1Followers[0].name === 'user1');
assert(post1Followers[1].name === 'user2');
assert(post1Followers.length === 2);
const post2Followers = await post2.getFollowers({order: [['name', 'ASC']]})
assert(post2Followers.length === 0);
// Same as getLikedPosts but with the user ID instead of the model object.
{
const user0Likes = await Post.findAll({
include: [{
model: User,
as: 'likers',
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,
as: 'likedPosts',
}],
order: [[{model: Post, as: 'likedPosts'}, 'body', 'ASC']],
})).likedPosts
assert(user0Likes[0].body === 'post0');
assert(user0Likes[1].body === 'post1');
assert(user0Likes.length === 2);
}
await sequelize.close();
})();

View File

@@ -0,0 +1,70 @@
#!/usr/bin/env node
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 },
}, {});
User.hasMany(Post);
Post.belongsTo(User);
await sequelize.sync({force: true});
// Create data.
const users = await User.bulkCreate([
{name: 'user0'},
{name: 'user1'},
{name: 'user2'},
{name: 'user3'},
])
const posts = await Post.bulkCreate([
{body: 'body00', UserId: users[0].id},
{body: 'body01', UserId: users[0].id},
{body: 'body10', UserId: users[1].id},
{body: 'body11', UserId: users[1].id},
{body: 'body20', UserId: users[2].id},
{body: 'body21', UserId: users[2].id},
{body: 'body30', UserId: users[3].id},
{body: 'body31', UserId: users[3].id},
])
// Get user from post and vice versa.
const user0Posts = await users[0].getPosts({order: [['body', 'ASC']]})
assert(user0Posts[0].body === 'body00')
assert(user0Posts[1].body === 'body01')
assert(user0Posts.length === 2)
const user1Posts = await users[1].getPosts({order: [['body', 'ASC']]})
assert(user1Posts[0].body === 'body10')
assert(user1Posts[1].body === 'body11')
assert(user1Posts.length === 2)
const post00User = await posts[0].getUser()
assert(post00User.name === 'user0')
const post01User = await posts[1].getUser()
assert(post01User.name === 'user0')
const post10User = await posts[2].getUser()
assert(post10User.name === 'user1')
const post11User = await posts[3].getUser()
assert(post11User.name === 'user1')
await sequelize.close();
})();

View File

@@ -0,0 +1,123 @@
#!/usr/bin/env node
// Two associations between two models: posts
// now have the author, and a mandatory reviewer.
// Requires us to use as do disambiguate them.
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',
define: {
timestamps: false
},
});
(async () => {
// Create the tables.
const User = sequelize.define('User', {
name: { type: DataTypes.STRING },
}, {});
const Post = sequelize.define('Post', {
body: { type: DataTypes.STRING },
}, {});
// TODO possible without specifying foreignKey? Feels like duplication.
// But without it, hasMany creates a column called UserId, in addition
// to the desired authorId, and then bad things happen.
User.hasMany(Post, {as: 'authoredPosts', foreignKey: 'authorId'});
Post.belongsTo(User, {as: 'author', foreignKey: 'authorId'});
User.hasMany(Post, {as: 'reviewedPosts', foreignKey: 'reviewerId'});
Post.belongsTo(User, {as: 'reviewer', foreignKey: 'reviewerId'});
await sequelize.sync({force: true});
// Create data.
const users = await User.bulkCreate([
{name: 'user0'},
{name: 'user1'},
{name: 'user2'},
{name: 'user3'},
])
const posts = await Post.bulkCreate([
{body: 'body00', authorId: users[0].id, reviewerId: users[0].id},
{body: 'body01', authorId: users[0].id, reviewerId: users[1].id},
{body: 'body10', authorId: users[1].id, reviewerId: users[2].id},
{body: 'body11', authorId: users[1].id, reviewerId: users[3].id},
{body: 'body20', authorId: users[2].id, reviewerId: users[0].id},
{body: 'body21', authorId: users[2].id, reviewerId: users[1].id},
{body: 'body30', authorId: users[3].id, reviewerId: users[2].id},
{body: 'body31', authorId: users[3].id, reviewerId: users[3].id},
])
// Get user from post and vice versa.
const user0AuthoredPosts = await users[0].getAuthoredPosts()
assert(user0AuthoredPosts[0].body === 'body00')
assert(user0AuthoredPosts[1].body === 'body01')
assert(user0AuthoredPosts.length === 2)
const user1AuthoredPosts = await users[1].getAuthoredPosts()
assert(user1AuthoredPosts[0].body === 'body10')
assert(user1AuthoredPosts[1].body === 'body11')
assert(user1AuthoredPosts.length === 2)
const user0ReviewedPosts = await users[0].getReviewedPosts()
assert(user0ReviewedPosts[0].body === 'body00')
assert(user0ReviewedPosts[1].body === 'body20')
assert(user0ReviewedPosts.length === 2)
const user1ReviewedPosts = await users[1].getReviewedPosts()
assert(user1ReviewedPosts[0].body === 'body01')
assert(user1ReviewedPosts[1].body === 'body21')
assert(user1ReviewedPosts.length === 2)
assert((await posts[0].getAuthor()).name === 'user0')
assert((await posts[1].getAuthor()).name === 'user0')
assert((await posts[2].getAuthor()).name === 'user1')
assert((await posts[3].getAuthor()).name === 'user1')
assert((await posts[0].getReviewer()).name === 'user0')
assert((await posts[1].getReviewer()).name === 'user1')
assert((await posts[2].getReviewer()).name === 'user2')
assert((await posts[3].getReviewer()).name === 'user3')
// Same as getAuthoredPosts but with the user ID instead of the model object.
{
const user0AuthoredPosts = await Post.findAll({
include: [{
model: User,
// We need the `as` here to disambiguate.
as: 'author',
where: {id: users[0].id},
}],
order: [['body', 'ASC']],
})
assert(user0AuthoredPosts[0].body === 'body00');
assert(user0AuthoredPosts[1].body === 'body01');
assert(user0AuthoredPosts.length === 2);
}
// Yet another way that can be more useful in nested includes.
{
const user0AuthoredPosts = (await User.findOne({
where: {id: users[0].id},
include: [{
model: Post,
as: 'authoredPosts',
}],
order: [[{model: Post, as: 'authoredPosts'}, 'body', 'ASC']],
})).authoredPosts
assert(user0AuthoredPosts[0].body === 'body00');
assert(user0AuthoredPosts[1].body === 'body01');
assert(user0AuthoredPosts.length === 2);
}
await sequelize.close();
})();

View File

@@ -37,7 +37,7 @@ const users = await User.bulkCreate([
const posts = await Post.bulkCreate([
{body: 'body00', UserId: users[0].id},
{body: 'body11', UserId: users[0].id},
{body: 'body01', UserId: users[0].id},
{body: 'body10', UserId: users[1].id},
{body: 'body11', UserId: users[1].id},
{body: 'body20', UserId: users[2].id},
@@ -108,7 +108,6 @@ await users[0].addFollows([users[1], users[2]])
postsFound.push(...followedUser.Posts)
}
postsFound.sort((x, y) => { return x.body < y.body ? -1 : x.body > y.body ? 1 : 0 })
// Note that what happens is that some of the
assert(postsFound[0].body === 'body11')
assert(postsFound[1].body === 'body20')
assert(postsFound.length === 2)
@@ -229,6 +228,37 @@ await users[0].addFollows([users[1], users[2]])
assert(postsFound[3].body === 'body1')
assert(postsFound.length === 4)
}
//// This is likely almost it. We just have to understand the undocumented custom on:
//// to specify from which side of the UserFollowsUser we are coming.
//{
// const postsFound = await Post.findAll({
// order: [[
// 'body',
// 'DESC'
// ]],
// subQuery: false,
// include: [
// {
// model: User,
// on: {'id': '$Post.User.FollowId$'},
// include: [
// {
// model: User,
// as: 'Follows',
// where: {id: users[0].id},
// }
// ],
// },
// ],
// })
// console.error(postsFound.length);
// assert.strictEqual(postsFound[0].body, 'body6')
// assert.strictEqual(postsFound[1].body, 'body5')
// assert.strictEqual(postsFound[0].body, 'body1')
// assert.strictEqual(postsFound[1].body, 'body2')
// assert.strictEqual(postsFound.length, 4)
//}
}
await sequelize.close();