mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-13 20:12:26 +00:00
move sequelize to cirosantilli.github.io
This commit is contained in:
@ -4,12 +4,8 @@
|
||||
"description": "https://cirosantilli.com/linux-kernel-module-cheat#node-js",
|
||||
"main": "alphanumeric.js",
|
||||
"dependencies": {
|
||||
"express": "^4.17.1",
|
||||
"express": "4.17.1",
|
||||
"mocha": "8.3.2",
|
||||
"pg": "8.5.1",
|
||||
"pg-hstore": "2.3.3",
|
||||
"sequelize": "6.5.1",
|
||||
"sqlite3": "5.0.2",
|
||||
"ts-node": "10.0.0"
|
||||
},
|
||||
"devDependencies": {},
|
||||
|
||||
@ -1,149 +0,0 @@
|
||||
#!/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 () => {
|
||||
const Comment = sequelize.define('Comment', {
|
||||
body: { type: DataTypes.STRING },
|
||||
});
|
||||
const User = sequelize.define('User', {
|
||||
name: { type: DataTypes.STRING },
|
||||
});
|
||||
User.hasMany(Comment)
|
||||
Comment.belongsTo(User)
|
||||
console.dir(User);
|
||||
await sequelize.sync({force: true});
|
||||
const u0 = await User.create({name: 'u0'})
|
||||
const u1 = await User.create({name: 'u1'})
|
||||
await Comment.create({body: 'u0c0', UserId: u0.id});
|
||||
await Comment.create({body: 'u0c1', UserId: u0.id});
|
||||
await Comment.create({body: 'u1c0', UserId: u1.id});
|
||||
|
||||
// Direct way.
|
||||
{
|
||||
const u0Comments = await Comment.findAll({
|
||||
where: { UserId: u0.id },
|
||||
order: [['id', 'ASC']],
|
||||
});
|
||||
assert(u0Comments[0].body === 'u0c0');
|
||||
assert(u0Comments[1].body === 'u0c1');
|
||||
assert(u0Comments[0].UserId === u0.id);
|
||||
assert(u0Comments[1].UserId === u0.id);
|
||||
// Not added as an object by default. Would require extra query.
|
||||
assert(u0Comments[0].User === undefined);
|
||||
assert(u0Comments[1].User === undefined);
|
||||
}
|
||||
|
||||
// Include data from the other side of the association in the query.
|
||||
{
|
||||
const u0Comments = await Comment.findAll({
|
||||
where: { UserId: u0.id },
|
||||
order: [['id', 'ASC']],
|
||||
include: User,
|
||||
// Equivalent alternatives in this case.
|
||||
//include: [User],
|
||||
//include: [{ model: User }],
|
||||
});
|
||||
assert(u0Comments[0].body === 'u0c0');
|
||||
assert(u0Comments[1].body === 'u0c1');
|
||||
assert(u0Comments[0].UserId === u0.id);
|
||||
assert(u0Comments[1].UserId === u0.id);
|
||||
// These did get added now.
|
||||
assert(u0Comments[0].User.name === 'u0');
|
||||
assert(u0Comments[1].User.name === 'u0');
|
||||
}
|
||||
|
||||
// Nicer higher level way.
|
||||
{
|
||||
const u0Comments = await u0.getComments({
|
||||
include: [{ model: User }],
|
||||
order: [['id', 'ASC']],
|
||||
});
|
||||
assert(u0Comments[0].body === 'u0c0');
|
||||
assert(u0Comments[1].body === 'u0c1');
|
||||
assert(u0Comments[0].User.name === 'u0');
|
||||
assert(u0Comments[1].User.name === 'u0');
|
||||
}
|
||||
|
||||
// If you REALLY wanted to not repeat the UserId magic constant everywhere, you could use User.associations.Comments.foreignKey
|
||||
// But it is such a mouthful, that nobody likely ever uses it?
|
||||
// https://stackoverflow.com/questions/34059081/how-do-i-reference-an-association-when-creating-a-row-in-sequelize-without-assum
|
||||
{
|
||||
await Comment.create({body: 'u0c2', [User.associations.Comments.foreignKey]: u0.id});
|
||||
// Syntax that we really would like instead.
|
||||
//await Comment.create({body: 'u0c2', User: u0});
|
||||
assert((await Comment.findAll({
|
||||
where: { [User.associations.Comments.foreignKey]: u0.id },
|
||||
})).length === 3);
|
||||
}
|
||||
|
||||
// Removal auto-cascades.
|
||||
{
|
||||
const u0id = u0.id
|
||||
await u0.destroy()
|
||||
assert((await Comment.findAll({
|
||||
where: { UserId: u0id },
|
||||
})).length === 0);
|
||||
assert((await Comment.findAll({
|
||||
where: { UserId: u1.id },
|
||||
})).length === 1);
|
||||
}
|
||||
|
||||
// as aliases.
|
||||
// Allows us to use a nicer name for a relation rather than the exact class name.
|
||||
// E.g. here we name the User of a Comment as a "author".
|
||||
// And mandatory do diambiguate multiple associations with a single type.
|
||||
{
|
||||
const CommentAs = sequelize.define('CommentAs', {
|
||||
body: { type: DataTypes.STRING },
|
||||
}, {});
|
||||
const UserAs = sequelize.define('UserAs', {
|
||||
name: { type: DataTypes.STRING },
|
||||
}, {});
|
||||
UserAs.hasMany(CommentAs)
|
||||
CommentAs.belongsTo(UserAs, {as: 'author'})
|
||||
await sequelize.sync({force: true});
|
||||
const u0 = await UserAs.create({name: 'u0'})
|
||||
const u1 = await UserAs.create({name: 'u1'})
|
||||
await CommentAs.create({body: 'u0c0', authorId: u0.id});
|
||||
await CommentAs.create({body: 'u0c1', authorId: u0.id});
|
||||
await CommentAs.create({body: 'u1c0', authorId: u1.id});
|
||||
|
||||
{
|
||||
const u0Comments = await CommentAs.findAll({
|
||||
where: { authorId: u0.id },
|
||||
order: [['id', 'ASC']],
|
||||
// Instead of include: UserAs
|
||||
include: 'author',
|
||||
});
|
||||
assert(u0Comments[0].body === 'u0c0');
|
||||
assert(u0Comments[1].body === 'u0c1');
|
||||
assert(u0Comments[0].authorId === u0.id);
|
||||
assert(u0Comments[1].authorId === u0.id);
|
||||
assert(u0Comments[0].author.name === 'u0');
|
||||
assert(u0Comments[1].author.name === 'u0');
|
||||
}
|
||||
|
||||
// Trying with the higher level getter.
|
||||
{
|
||||
// TODO
|
||||
// u0.getComments is not a function
|
||||
//const u0Comments = await u0.getComments({
|
||||
// include: 'author',
|
||||
//});
|
||||
//assert(u0Comments[0].body === 'u0c0');
|
||||
//assert(u0Comments[1].body === 'u0c1');
|
||||
//assert(u0Comments[0].author.name === 'u0');
|
||||
//assert(u0Comments[1].author.name === 'u0');
|
||||
}
|
||||
}
|
||||
await sequelize.close();
|
||||
})();
|
||||
@ -1,162 +0,0 @@
|
||||
#!/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);
|
||||
assert.strictEqual(await user0.countPosts(), 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();
|
||||
})();
|
||||
@ -1,116 +0,0 @@
|
||||
#!/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 },
|
||||
});
|
||||
const UserLikesPost = sequelize.define('UserLikesPost', {
|
||||
UserId: {
|
||||
type: DataTypes.INTEGER,
|
||||
references: {
|
||||
model: User,
|
||||
key: 'id'
|
||||
}
|
||||
},
|
||||
PostId: {
|
||||
type: DataTypes.INTEGER,
|
||||
references: {
|
||||
model: Post,
|
||||
key: 'id'
|
||||
}
|
||||
},
|
||||
score: {
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
});
|
||||
// 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,
|
||||
// `Score` INTEGER,
|
||||
// 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 some useres like some posts.
|
||||
await user0.addPost(post0, {through: {score: 1}})
|
||||
await user1.addPost(post1, {through: {score: 2}})
|
||||
await user1.addPost(post2, {through: {score: 3}})
|
||||
|
||||
// Find what user0 likes.
|
||||
const user0Likes = await user0.getPosts({order: [['body', 'ASC']]})
|
||||
assert(user0Likes[0].body === 'post0');
|
||||
assert(user0Likes[0].UserLikesPost.score === 1);
|
||||
assert(user0Likes.length === 1);
|
||||
|
||||
// Find what user1 likes.
|
||||
const user1Likes = await user1.getPosts({order: [['body', 'ASC']]})
|
||||
assert(user1Likes[0].body === 'post1');
|
||||
assert(user1Likes[0].UserLikesPost.score === 2);
|
||||
assert(user1Likes[1].body === 'post2');
|
||||
assert(user1Likes[1].UserLikesPost.score === 3);
|
||||
assert(user1Likes.length === 2);
|
||||
|
||||
// Where on the custom through table column.
|
||||
// https://stackoverflow.com/questions/38857156/how-to-query-many-to-many-relationship-sequelize
|
||||
{
|
||||
const user1LikesWithScore3 = await Post.findAll({
|
||||
include: [{
|
||||
model: User,
|
||||
where: {id: user1.id},
|
||||
through: {where: {score: 3}},
|
||||
}],
|
||||
})
|
||||
assert(user1LikesWithScore3[0].body === 'post2');
|
||||
assert(user1LikesWithScore3[0].UserLikesPost.score === 3);
|
||||
assert(user1LikesWithScore3.length === 1);
|
||||
}
|
||||
|
||||
// TODO: this doesn't work. Possible at all in a single addUsers call?
|
||||
// Make user0 and user2 like post1
|
||||
// This method automatically generated.
|
||||
//await post1.addUsers(
|
||||
// [user0, user2],
|
||||
// {through: [
|
||||
// {score: 2},
|
||||
// {score: 3},
|
||||
// ]}
|
||||
//)
|
||||
|
||||
await sequelize.close();
|
||||
})();
|
||||
@ -1,157 +0,0 @@
|
||||
#!/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.
|
||||
// as is mandatory to disambiguate which one we want to get.
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
// Alternatively, we can also pass the association object instead of model + as.
|
||||
// This is actually nicer!
|
||||
{
|
||||
const user0Likes = await Post.findAll({
|
||||
include: [{
|
||||
association: Post.associations.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();
|
||||
})();
|
||||
@ -1,124 +0,0 @@
|
||||
#!/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',
|
||||
define: {
|
||||
timestamps: false
|
||||
},
|
||||
});
|
||||
|
||||
(async () => {
|
||||
|
||||
// Create the tables.
|
||||
const User = sequelize.define('User', {
|
||||
name: { type: DataTypes.STRING },
|
||||
}, {});
|
||||
User.belongsToMany(User, {through: 'UserFollowUser', as: 'Follows'});
|
||||
await sequelize.sync({force: true});
|
||||
|
||||
// Create some users.
|
||||
|
||||
const user0 = await User.create({name: 'user0'})
|
||||
const user1 = await User.create({name: 'user1'})
|
||||
const user2 = await User.create({name: 'user2'})
|
||||
const user3 = await User.create({name: '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)
|
||||
|
||||
// Check that the follows worked.
|
||||
const user0Follows = await user0.getFollows({order: [['name', 'ASC']]})
|
||||
assert(user0Follows[0].name === 'user1');
|
||||
assert(user0Follows[1].name === 'user2');
|
||||
assert(user0Follows.length === 2);
|
||||
|
||||
const user1Follows = await user1.getFollows({order: [['name', 'ASC']]})
|
||||
assert(user1Follows.length === 0);
|
||||
|
||||
const user2Follows = await user2.getFollows({order: [['name', 'ASC']]})
|
||||
assert(user2Follows[0].name === 'user0');
|
||||
assert(user2Follows.length === 1);
|
||||
|
||||
const user3Follows = await user3.getFollows({order: [['name', 'ASC']]})
|
||||
assert(user3Follows[0].name === 'user0');
|
||||
assert(user3Follows.length === 1);
|
||||
|
||||
// Same but with ID instead of object.
|
||||
// Also get rid of all useless fields from the trough table.
|
||||
{
|
||||
const user0Follows = (await User.findOne({
|
||||
where: {id: user0.id},
|
||||
attributes: [],
|
||||
include: [{
|
||||
model: User,
|
||||
as: 'Follows',
|
||||
through: {attributes: []},
|
||||
}],
|
||||
})).Follows
|
||||
assert(user0Follows[0].name === 'user1');
|
||||
assert(user0Follows[1].name === 'user2');
|
||||
assert(user0Follows.length === 2);
|
||||
}
|
||||
|
||||
//// Yet another method with the many-to-many reversed.
|
||||
//// TODO close to working, but on is being ignored...
|
||||
//{
|
||||
// const user0Follows = await User.findAll({
|
||||
// include: [{
|
||||
// model: User,
|
||||
// as: 'Follows',
|
||||
// on: {
|
||||
// '$User.UserFollowUser.FollowIdasdf$': { [Sequelize.Op.col]: 'User.user_id' },
|
||||
// '$User.UserFollowUser.UserId$': user0.id,
|
||||
// },
|
||||
// attributes: [],
|
||||
// through: {attributes: []},
|
||||
// }],
|
||||
// order: [['name', 'ASC']],
|
||||
// })
|
||||
// // TODO
|
||||
// //assert(user0Follows[0].name === 'user1');
|
||||
// //assert(user0Follows[1].name === 'user2');
|
||||
// //assert(user0Follows.length === 2);
|
||||
//}
|
||||
|
||||
// Find users that follow user0
|
||||
{
|
||||
const followsUser0 = await User.findAll({
|
||||
include: [{
|
||||
model: User,
|
||||
as: 'Follows',
|
||||
where: {id: user0.id},
|
||||
attributes: [],
|
||||
through: {attributes: []}
|
||||
}],
|
||||
order: [['name', 'ASC']],
|
||||
})
|
||||
assert(followsUser0[0].name === 'user2');
|
||||
assert(followsUser0[1].name === 'user3');
|
||||
assert(followsUser0.length === 2);
|
||||
}
|
||||
|
||||
// has methods
|
||||
assert(!await user0.hasFollow(user0))
|
||||
assert(!await user0.hasFollow(user0.id))
|
||||
assert( await user0.hasFollow(user1))
|
||||
assert( await user0.hasFollow(user2))
|
||||
assert(!await user0.hasFollow(user3))
|
||||
|
||||
// Count method
|
||||
assert(await user0.countFollows() === 2)
|
||||
|
||||
await sequelize.close();
|
||||
})();
|
||||
@ -1,114 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// Like association_many_to_many_same_model but with a super many to many,
|
||||
// i.e. explicit through table relations).
|
||||
|
||||
const assert = require('assert');
|
||||
const path = require('path');
|
||||
|
||||
const { Sequelize, DataTypes, Op } = 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 UserFollowUser = sequelize.define('UserFollowUser', {
|
||||
UserId: {
|
||||
type: DataTypes.INTEGER,
|
||||
references: {
|
||||
model: User,
|
||||
key: 'id'
|
||||
}
|
||||
},
|
||||
FollowId: {
|
||||
type: DataTypes.INTEGER,
|
||||
references: {
|
||||
model: User,
|
||||
key: 'id'
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
// Super many to many. Only works with explicit table for some reason.
|
||||
User.belongsToMany(User, {through: UserFollowUser, as: 'Follows'});
|
||||
UserFollowUser.belongsTo(User)
|
||||
User.hasMany(UserFollowUser)
|
||||
|
||||
await sequelize.sync({force: true});
|
||||
|
||||
// Create some users.
|
||||
|
||||
const user0 = await User.create({name: 'user0'})
|
||||
const user1 = await User.create({name: 'user1'})
|
||||
const user2 = await User.create({name: 'user2'})
|
||||
const user3 = await User.create({name: 'user3'})
|
||||
await user0.addFollows([user1, user2])
|
||||
await user2.addFollow(user0)
|
||||
await user3.addFollow(user0)
|
||||
|
||||
// Find all users that a user follows.
|
||||
const user0Follows = await user0.getFollows({order: [['name', 'ASC']]})
|
||||
assert(user0Follows[0].name === 'user1');
|
||||
assert(user0Follows[1].name === 'user2');
|
||||
assert(user0Follows.length === 2);
|
||||
|
||||
const user1Follows = await user1.getFollows({order: [['name', 'ASC']]})
|
||||
assert(user1Follows.length === 0);
|
||||
|
||||
const user2Follows = await user2.getFollows({order: [['name', 'ASC']]})
|
||||
assert(user2Follows[0].name === 'user0');
|
||||
assert(user2Follows.length === 1);
|
||||
|
||||
const user3Follows = await user3.getFollows({order: [['name', 'ASC']]})
|
||||
assert(user3Follows[0].name === 'user0');
|
||||
assert(user3Follows.length === 1);
|
||||
|
||||
// Same but with explicit id.
|
||||
{
|
||||
const user0Follows = (await User.findOne({
|
||||
where: {id: user0.id},
|
||||
attributes: [],
|
||||
include: [{
|
||||
model: User,
|
||||
as: 'Follows',
|
||||
through: {attributes: []},
|
||||
}],
|
||||
})).Follows
|
||||
assert(user0Follows[0].name === 'user1');
|
||||
assert(user0Follows[1].name === 'user2');
|
||||
assert(user0Follows.length === 2);
|
||||
}
|
||||
|
||||
// Another method with the many-to-many reversed.
|
||||
// Using the super many to many is the only way I know of doing this so far.
|
||||
// which is a pain.
|
||||
{
|
||||
const user0Follows = await User.findAll({
|
||||
include: [{
|
||||
model: UserFollowUser,
|
||||
attributes: [],
|
||||
on: {
|
||||
FollowId: { [Op.col]: 'User.id' },
|
||||
},
|
||||
where: {UserId: user0.id}
|
||||
}],
|
||||
order: [['name', 'ASC']],
|
||||
})
|
||||
assert(user0Follows[0].name === 'user1');
|
||||
assert(user0Follows[1].name === 'user2');
|
||||
assert(user0Follows.length === 2);
|
||||
}
|
||||
|
||||
await sequelize.close();
|
||||
})();
|
||||
@ -1,70 +0,0 @@
|
||||
#!/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();
|
||||
})();
|
||||
@ -1,123 +0,0 @@
|
||||
#!/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();
|
||||
})();
|
||||
@ -1,294 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// Find all posts by users that a given user follows.
|
||||
// https://stackoverflow.com/questions/42632943/sequelize-multiple-where-clause
|
||||
|
||||
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 },
|
||||
});
|
||||
User.belongsToMany(User, {through: 'UserFollowUser', as: 'Follows'});
|
||||
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},
|
||||
])
|
||||
|
||||
await users[0].addFollows([users[1], users[2]])
|
||||
|
||||
// Get all posts by authors that user0 follows.
|
||||
// The posts are placed inside their respetive authors under .Posts
|
||||
// so we loop to gather all of them.
|
||||
{
|
||||
const user0Follows = (await User.findByPk(users[0].id, {
|
||||
include: [
|
||||
{
|
||||
model: User,
|
||||
as: 'Follows',
|
||||
include: [
|
||||
{
|
||||
model: Post,
|
||||
}
|
||||
],
|
||||
},
|
||||
],
|
||||
})).Follows
|
||||
const postsFound = []
|
||||
for (const followedUser of user0Follows) {
|
||||
postsFound.push(...followedUser.Posts)
|
||||
}
|
||||
postsFound.sort((x, y) => { return x.body < y.body ? -1 : x.body > y.body ? 1 : 0 })
|
||||
assert(postsFound[0].body === 'body10')
|
||||
assert(postsFound[1].body === 'body11')
|
||||
assert(postsFound[2].body === 'body20')
|
||||
assert(postsFound[3].body === 'body21')
|
||||
assert(postsFound.length === 4)
|
||||
}
|
||||
|
||||
// Similar to the above, but now with ordering, offset and limit.
|
||||
// The posts are placed inside their respetive authors under .Posts
|
||||
// The only difference is that posts that we didn't select got removed.
|
||||
{
|
||||
const user0Follows = (await User.findByPk(users[0].id, {
|
||||
offset: 1,
|
||||
limit: 2,
|
||||
// TODO why is this needed? It does try to make a subquery otherwise, and then it doesn't work.
|
||||
// https://selleo.com/til/posts/ddesmudzmi-offset-pagination-with-subquery-in-sequelize-
|
||||
subQuery: false,
|
||||
include: [
|
||||
{
|
||||
model: User,
|
||||
as: 'Follows',
|
||||
include: [
|
||||
{
|
||||
model: Post,
|
||||
}
|
||||
],
|
||||
},
|
||||
],
|
||||
})).Follows
|
||||
assert(user0Follows[0].name === 'user1')
|
||||
assert(user0Follows[1].name === 'user2')
|
||||
assert(user0Follows.length === 2)
|
||||
const postsFound = []
|
||||
for (const followedUser of user0Follows) {
|
||||
postsFound.push(...followedUser.Posts)
|
||||
}
|
||||
postsFound.sort((x, y) => { return x.body < y.body ? -1 : x.body > y.body ? 1 : 0 })
|
||||
assert(postsFound[0].body === 'body11')
|
||||
assert(postsFound[1].body === 'body20')
|
||||
assert(postsFound.length === 2)
|
||||
|
||||
// Same as above, but now with DESC ordering.
|
||||
{
|
||||
const user0Follows = (await User.findByPk(users[0].id, {
|
||||
order: [[
|
||||
{model: User, as: 'Follows'},
|
||||
Post,
|
||||
'body',
|
||||
'DESC'
|
||||
]],
|
||||
offset: 1,
|
||||
limit: 2,
|
||||
subQuery: false,
|
||||
include: [
|
||||
{
|
||||
model: User,
|
||||
as: 'Follows',
|
||||
include: [
|
||||
{
|
||||
model: Post,
|
||||
}
|
||||
],
|
||||
},
|
||||
],
|
||||
})).Follows
|
||||
// Note how user ordering is also reversed from an ASC.
|
||||
// it likely takes the use that has the first post.
|
||||
assert(user0Follows[0].name === 'user2')
|
||||
assert(user0Follows[1].name === 'user1')
|
||||
assert(user0Follows.length === 2)
|
||||
const postsFound = []
|
||||
for (const followedUser of user0Follows) {
|
||||
postsFound.push(...followedUser.Posts)
|
||||
}
|
||||
// In this very specific data case, this would not be needed.
|
||||
// because user2 has the second post body and user1 has the first
|
||||
// alphabetically.
|
||||
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 === 'body20')
|
||||
assert(postsFound[1].body === 'body11')
|
||||
assert(postsFound.length === 2)
|
||||
}
|
||||
|
||||
// Here user2 would have no post hits due to the limit,
|
||||
// so it is entirely pruned from the user list as desired.
|
||||
// Otherwise we would fetch a lot of unwanted user data
|
||||
// in a large database.
|
||||
const user0FollowsLimit2 = (await User.findByPk(users[0].id, {
|
||||
limit: 2,
|
||||
subQuery: false,
|
||||
include: [
|
||||
{
|
||||
model: User,
|
||||
as: 'Follows',
|
||||
include: [ { model: Post } ],
|
||||
},
|
||||
],
|
||||
})).Follows
|
||||
assert(user0FollowsLimit2[0].name === 'user1')
|
||||
assert(user0FollowsLimit2.length === 1)
|
||||
|
||||
// Get just the count of the posts authored by useres followed by user0.
|
||||
// attributes: [] excludes all other data from the SELECT of the querries
|
||||
// to optimize things a bit.
|
||||
// https://stackoverflow.com/questions/37817808/counting-associated-entries-with-sequelize
|
||||
{
|
||||
const user0Follows = await User.findByPk(users[0].id, {
|
||||
attributes: [
|
||||
[Sequelize.fn('COUNT', Sequelize.col('Follows.Posts.id')), 'count']
|
||||
],
|
||||
include: [
|
||||
{
|
||||
model: User,
|
||||
as: 'Follows',
|
||||
attributes: [],
|
||||
through: {attributes: []},
|
||||
include: [{
|
||||
model: Post,
|
||||
attributes: [],
|
||||
}],
|
||||
},
|
||||
],
|
||||
})
|
||||
assert.strictEqual(user0Follows.dataValues.count, 4);
|
||||
}
|
||||
|
||||
// Case in which our post-sorting is needed.
|
||||
// TODO: possible to get sequelize to do this for us by returning
|
||||
// a flat array directly?
|
||||
// It's not big deal since the LIMITed result should be small,
|
||||
// but feels wasteful.
|
||||
// https://stackoverflow.com/questions/41502699/return-flat-object-from-sequelize-with-association
|
||||
// https://github.com/sequelize/sequelize/issues/4419
|
||||
{
|
||||
await Post.truncate({restartIdentity: true})
|
||||
const posts = await Post.bulkCreate([
|
||||
{body: 'body0', UserId: users[0].id},
|
||||
{body: 'body1', UserId: users[1].id},
|
||||
{body: 'body2', UserId: users[2].id},
|
||||
{body: 'body3', UserId: users[3].id},
|
||||
{body: 'body4', UserId: users[0].id},
|
||||
{body: 'body5', UserId: users[1].id},
|
||||
{body: 'body6', UserId: users[2].id},
|
||||
{body: 'body7', UserId: users[3].id},
|
||||
])
|
||||
const user0Follows = (await User.findByPk(users[0].id, {
|
||||
order: [[
|
||||
{model: User, as: 'Follows'},
|
||||
Post,
|
||||
'body',
|
||||
'DESC'
|
||||
]],
|
||||
subQuery: false,
|
||||
include: [
|
||||
{
|
||||
model: User,
|
||||
as: 'Follows',
|
||||
include: [
|
||||
{
|
||||
model: Post,
|
||||
}
|
||||
],
|
||||
},
|
||||
],
|
||||
})).Follows
|
||||
assert(user0Follows[0].name === 'user2')
|
||||
assert(user0Follows[1].name === 'user1')
|
||||
assert(user0Follows.length === 2)
|
||||
const postsFound = []
|
||||
for (const followedUser of user0Follows) {
|
||||
postsFound.push(...followedUser.Posts)
|
||||
}
|
||||
// We need this here, otherwise we would get all user2 posts first:
|
||||
// body6, body2, body5, body1
|
||||
postsFound.sort((x, y) => { return x.body < y.body ? 1 : x.body > y.body ? -1 : 0 })
|
||||
assert(postsFound[0].body === 'body6')
|
||||
assert(postsFound[1].body === 'body5')
|
||||
assert(postsFound[2].body === 'body2')
|
||||
assert(postsFound[3].body === 'body1')
|
||||
assert(postsFound.length === 4)
|
||||
}
|
||||
|
||||
// This almost achieves the flat array return. We just have to understand the undocumented custom on:
|
||||
// to specify from which side of the UserFollowsUser we are coming. The on:
|
||||
// is ignored without super many to many unfortunately, the below just returns all posts.
|
||||
// We only managed to achieve this with super many to many so far.
|
||||
{
|
||||
const postsFound = await Post.findAll({
|
||||
order: [[
|
||||
'body',
|
||||
'DESC'
|
||||
]],
|
||||
subQuery: false,
|
||||
include: [
|
||||
{
|
||||
model: User,
|
||||
//on: {idasdf: '$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[2].body, 'body2')
|
||||
//assert.strictEqual(postsFound[3].body, 'body1')
|
||||
assert.strictEqual(postsFound.length, 4)
|
||||
}
|
||||
}
|
||||
|
||||
await sequelize.close();
|
||||
})();
|
||||
@ -1,111 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// Like association_nested_include.js but with a super many to many.
|
||||
|
||||
const assert = require('assert');
|
||||
const path = require('path');
|
||||
|
||||
const { Sequelize, DataTypes, Op } = 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 },
|
||||
});
|
||||
const UserFollowUser = sequelize.define('UserFollowUser', {
|
||||
UserId: {
|
||||
type: DataTypes.INTEGER,
|
||||
references: {
|
||||
model: User,
|
||||
key: 'id'
|
||||
}
|
||||
},
|
||||
FollowId: {
|
||||
type: DataTypes.INTEGER,
|
||||
references: {
|
||||
model: User,
|
||||
key: 'id'
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
// Super many to many.
|
||||
User.belongsToMany(User, {through: UserFollowUser, as: 'Follows'});
|
||||
UserFollowUser.belongsTo(User)
|
||||
User.hasMany(UserFollowUser)
|
||||
|
||||
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: 'body0', UserId: users[0].id},
|
||||
{body: 'body1', UserId: users[1].id},
|
||||
{body: 'body2', UserId: users[2].id},
|
||||
{body: 'body3', UserId: users[3].id},
|
||||
{body: 'body4', UserId: users[0].id},
|
||||
{body: 'body5', UserId: users[1].id},
|
||||
{body: 'body6', UserId: users[2].id},
|
||||
{body: 'body7', UserId: users[3].id},
|
||||
])
|
||||
await users[0].addFollows([users[1], users[2]])
|
||||
|
||||
// Get all the posts by authors that user0 follows.
|
||||
// without any post process sorting. We only managed to to this
|
||||
// with a super many to many, because that allows us to specify
|
||||
// a reversed order in the through table with `on`, since we need to
|
||||
// match with `FollowId` and not `UserId`.
|
||||
{
|
||||
const postsFound = await Post.findAll({
|
||||
order: [[
|
||||
'body',
|
||||
'DESC'
|
||||
]],
|
||||
include: [
|
||||
{
|
||||
model: User,
|
||||
attributes: [],
|
||||
required: true,
|
||||
include: [
|
||||
{
|
||||
model: UserFollowUser,
|
||||
on: {
|
||||
FollowId: {[Op.col]: 'User.id' },
|
||||
},
|
||||
attributes: [],
|
||||
where: {UserId: users[0].id},
|
||||
}
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
assert.strictEqual(postsFound[0].body, 'body6')
|
||||
assert.strictEqual(postsFound[1].body, 'body5')
|
||||
assert.strictEqual(postsFound[2].body, 'body2')
|
||||
assert.strictEqual(postsFound[3].body, 'body1')
|
||||
assert.strictEqual(postsFound.length, 4)
|
||||
}
|
||||
|
||||
await sequelize.close();
|
||||
})();
|
||||
@ -1,61 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// https://github.com/sequelize/sequelize/issues/3534
|
||||
// https://github.com/sequelize/sequelize/issues/8586
|
||||
|
||||
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 () => {
|
||||
|
||||
const IntegerNames = sequelize.define('IntegerNames',
|
||||
{
|
||||
value: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
},
|
||||
name2: {
|
||||
type: DataTypes.STRING,
|
||||
},
|
||||
|
||||
},
|
||||
{
|
||||
hooks: {
|
||||
beforeValidate: (integerName, options) => {
|
||||
integerName.name2 = integerName.name + 'asdf'
|
||||
// This fixes the failure.
|
||||
//options.fields.push('name2');
|
||||
}
|
||||
,}
|
||||
},
|
||||
);
|
||||
await IntegerNames.sync({force: true})
|
||||
await IntegerNames.create({value: 2, name: 'two'});
|
||||
await IntegerNames.create({value: 3, name: 'three'});
|
||||
await IntegerNames.create({value: 5, name: 'five'});
|
||||
|
||||
const integerName = await IntegerNames.findOne({ where: { value: 2 } });
|
||||
assert.strictEqual(integerName.name, 'two');
|
||||
assert.strictEqual(integerName.name2, 'twoasdf');
|
||||
integerName.name = 'TWO'
|
||||
integerName.save();
|
||||
|
||||
const integerName2 = await IntegerNames.findOne({ where: { value: 2 } });
|
||||
assert.strictEqual(integerName2.name, 'TWO');
|
||||
// Fails.
|
||||
//assert.strictEqual(integerName2.name2, 'TWOasdf');
|
||||
|
||||
await sequelize.close();
|
||||
|
||||
})();
|
||||
@ -1,127 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// Trying to get everything in the database camel cased, columns lowercase, tables uppercase.
|
||||
// The defaults documented on getting started documentation do uppercase foreign keys, an
|
||||
// lowercase non-foreign keys. It's a mess.
|
||||
|
||||
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 },
|
||||
});
|
||||
const UserFollowsUser = sequelize.define('UserFollowsUser', {
|
||||
userId: {
|
||||
type: DataTypes.INTEGER,
|
||||
references: {
|
||||
model: User,
|
||||
key: 'id'
|
||||
}
|
||||
},
|
||||
followId: {
|
||||
type: DataTypes.INTEGER,
|
||||
references: {
|
||||
model: User,
|
||||
key: 'id'
|
||||
}
|
||||
},
|
||||
});
|
||||
User.belongsToMany(User, {
|
||||
through: UserFollowsUser,
|
||||
as: 'follows',
|
||||
foreignKey: 'userId',
|
||||
otherKey: 'followId',
|
||||
});
|
||||
User.hasMany(Post, {foreignKey: 'authorId'});
|
||||
Post.belongsTo(User, {foreignKey: 'authorId'});
|
||||
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},
|
||||
{body: 'body01', authorId: users[0].id},
|
||||
{body: 'body10', authorId: users[1].id},
|
||||
{body: 'body11', authorId: users[1].id},
|
||||
{body: 'body20', authorId: users[2].id},
|
||||
{body: 'body21', authorId: users[2].id},
|
||||
{body: 'body30', authorId: users[3].id},
|
||||
{body: 'body31', authorId: users[3].id},
|
||||
])
|
||||
await users[0].addFollows([users[1], users[2]])
|
||||
|
||||
// Check case of auto-getters.
|
||||
|
||||
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')
|
||||
|
||||
// Check case of as;
|
||||
{
|
||||
const user0Follows = (await User.findByPk(users[0].id, {
|
||||
include: [
|
||||
{
|
||||
model: User,
|
||||
as: 'follows',
|
||||
include: [
|
||||
{
|
||||
model: Post,
|
||||
}
|
||||
],
|
||||
},
|
||||
],
|
||||
})).follows
|
||||
const postsFound = []
|
||||
for (const followedUser of user0Follows) {
|
||||
postsFound.push(...followedUser.Posts)
|
||||
}
|
||||
postsFound.sort((x, y) => { return x.body < y.body ? -1 : x.body > y.body ? 1 : 0 })
|
||||
assert(postsFound[0].body === 'body10')
|
||||
assert(postsFound[1].body === 'body11')
|
||||
assert(postsFound[2].body === 'body20')
|
||||
assert(postsFound[3].body === 'body21')
|
||||
assert(postsFound.length === 4)
|
||||
}
|
||||
|
||||
await sequelize.close();
|
||||
})();
|
||||
@ -1,47 +0,0 @@
|
||||
#!/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',
|
||||
define: {
|
||||
timestamps: false
|
||||
},
|
||||
});
|
||||
(async () => {
|
||||
const Tag = sequelize.define('Tag', {
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
unique: true,
|
||||
},
|
||||
});
|
||||
await sequelize.sync({force: true})
|
||||
await Tag.create({name: 't0'})
|
||||
|
||||
// Individual create does not have the option for some reason.
|
||||
// Apparently you're just supposed to catch.
|
||||
// https://github.com/sequelize/sequelize/issues/4513
|
||||
//await Tag.create({name: 't0', ignoreDuplicates: true})
|
||||
|
||||
// SQLite: INSERT OR IGNORE INTO as desired.
|
||||
const tags = await Tag.bulkCreate(
|
||||
[
|
||||
{name: 't0'},
|
||||
{name: 't1'},
|
||||
{name: 't1'},
|
||||
{name: 't2'},
|
||||
],
|
||||
{
|
||||
ignoreDuplicates: true,
|
||||
}
|
||||
)
|
||||
const tagsFound = await Tag.findAll({order: [['name', 'ASC']]})
|
||||
assert.strictEqual(tagsFound[0].name, 't0')
|
||||
assert.strictEqual(tagsFound[1].name, 't1')
|
||||
assert.strictEqual(tagsFound[2].name, 't2')
|
||||
assert.strictEqual(tagsFound.length, 3)
|
||||
|
||||
await sequelize.close();
|
||||
})();
|
||||
@ -1,33 +0,0 @@
|
||||
#!/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 () => {
|
||||
await sequelize.authenticate();
|
||||
const IntegerNames = sequelize.define('IntegerNames', {
|
||||
value: {
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
},
|
||||
});
|
||||
await IntegerNames.sync({force: true})
|
||||
await IntegerNames.create({value: 2, name: 'two'});
|
||||
await IntegerNames.create({value: 3, name: 'three'});
|
||||
await IntegerNames.create({value: 5, name: 'five'});
|
||||
const integerName5 = await IntegerNames.findOne({ where: { value: 5 } });
|
||||
integerName5.increment('value')
|
||||
// Sequelize updates, but others don't...
|
||||
console.error(integerName5.value);
|
||||
const integerName6 = await IntegerNames.findOne({ where: { value: 6 } });
|
||||
assert.strictEqual(integerName6.name, 'five')
|
||||
await sequelize.close();
|
||||
})();
|
||||
@ -1,146 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// https://cirosantilli.com/sequelize
|
||||
//
|
||||
// Before running this:
|
||||
// * ensure that you can use peer authentication without password
|
||||
// from the command line, i.e. `psql` works
|
||||
// * create the database for our test:
|
||||
// ``
|
||||
// createdb lkmc-nodejs
|
||||
// ``
|
||||
|
||||
const assert = require('assert');
|
||||
const path = require('path');
|
||||
|
||||
const { Sequelize, DataTypes, Op } = require('sequelize');
|
||||
|
||||
// To use the URI syntax, we need an explcit username and password.
|
||||
// But the second constructor works with peer authentication.
|
||||
// https://stackoverflow.com/questions/46207155/sequelize-and-peer-authentication-for-postgres
|
||||
//
|
||||
// Fails
|
||||
//const sequelize = new Sequelize('postgres://user:password@localhost:5432/lkmc-nodejs')
|
||||
//
|
||||
// Works with peer authentication:
|
||||
//const sequelize = new Sequelize('lkmc-nodejs', undefined, undefined, {
|
||||
// host: '/var/run/postgresql',
|
||||
// dialect: 'postgres',
|
||||
// logging: false,
|
||||
//});
|
||||
const sequelize = new Sequelize({
|
||||
dialect: 'sqlite',
|
||||
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
|
||||
});
|
||||
|
||||
// OMG fuck this asynchronous bullshit:
|
||||
// https://stackoverflow.com/questions/39928452/execute-sequelize-queries-synchronously/43250120
|
||||
(async () => {
|
||||
|
||||
// Connection sanity check.
|
||||
// https://stackoverflow.com/questions/19429152/check-mysql-connection-in-sequelize/31115934
|
||||
await sequelize.authenticate();
|
||||
|
||||
const IntegerNames = sequelize.define('IntegerNames', {
|
||||
value: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
},
|
||||
});
|
||||
|
||||
// Create the database defined by `sequelize.define`.
|
||||
await IntegerNames.sync({force: true})
|
||||
// After this:
|
||||
//
|
||||
// psql lkmc-nodejs -c '\dt'
|
||||
//
|
||||
// gives:
|
||||
//
|
||||
// List of relations
|
||||
// Schema | Name | Type | Owner
|
||||
// --------+--------------+-------+-------
|
||||
// public | IntegerNames | table | ciro
|
||||
// (2 rows)
|
||||
//
|
||||
// and:
|
||||
//
|
||||
// psql lkmc-nodejs -c '\d+ "IntegerNames"'
|
||||
//
|
||||
// gives:
|
||||
//
|
||||
// Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
|
||||
// -----------+--------------------------+-----------+----------+--------------------------------------------+----------+--------------+-------------
|
||||
// id | integer | | not null | nextval('"IntegerNames_id_seq"'::regclass) | plain | |
|
||||
// value | integer | | not null | | plain | |
|
||||
// name | character varying(255) | | | | extended | |
|
||||
// createdAt | timestamp with time zone | | not null | | plain | |
|
||||
// updatedAt | timestamp with time zone | | not null | | plain | |
|
||||
// Indexes:
|
||||
// "IntegerNames_pkey" PRIMARY KEY, btree (id)
|
||||
|
||||
await IntegerNames.create({value: 2, name: 'two'});
|
||||
await IntegerNames.create({value: 3, name: 'three'});
|
||||
await IntegerNames.create({value: 5, name: 'five'});
|
||||
// psql lkmc-nodejs -c 'SELECT * FROM "IntegerNames";'
|
||||
//
|
||||
// gives:
|
||||
//
|
||||
// id | value | name | createdAt | updatedAt
|
||||
// ----+-------+-------+----------------------------+----------------------------
|
||||
// 1 | 2 | two | 2021-03-19 19:12:08.436+00 | 2021-03-19 19:12:08.436+00
|
||||
// 2 | 3 | three | 2021-03-19 19:12:08.436+00 | 2021-03-19 19:12:08.436+00
|
||||
// 3 | 5 | five | 2021-03-19 19:12:08.437+00 | 2021-03-19 19:12:08.437+00
|
||||
// (3 rows)
|
||||
|
||||
let integerNames = await IntegerNames.findAll({
|
||||
where: {
|
||||
value: 2
|
||||
}
|
||||
});
|
||||
assert.strictEqual(integerNames[0].name, 'two');
|
||||
assert.strictEqual(integerNames.length, 1);
|
||||
|
||||
// SELECT and destroy: https://stackoverflow.com/questions/8402597/sequelize-js-delete-query
|
||||
await IntegerNames.destroy({
|
||||
where: {
|
||||
value: { [Op.gt]: 2 },
|
||||
},
|
||||
limit: 1,
|
||||
});
|
||||
integerNames = await IntegerNames.findAll({order: [['value', 'ASC']]})
|
||||
assert.strictEqual(integerNames[0].name, 'two');
|
||||
assert.strictEqual(integerNames[1].name, 'five');
|
||||
assert.strictEqual(integerNames.length, 2);
|
||||
|
||||
// Truncate all tables.
|
||||
// https://stackoverflow.com/questions/47816162/wipe-all-tables-in-a-schema-sequelize-nodejs/66985334#66985334
|
||||
await sequelize.truncate();
|
||||
assert.strictEqual(await IntegerNames.count(), 0);
|
||||
|
||||
// Datetime. Automatically converts to/from date objects.
|
||||
const Dates = sequelize.define('Dates', {
|
||||
date: {
|
||||
type: DataTypes.DATE,
|
||||
},
|
||||
}, {});
|
||||
await Dates.sync({force: true})
|
||||
let dateCreate = await Dates.create({date: new Date(2000, 0, 1, 2, 3, 4, 5)});
|
||||
await Dates.create({date: new Date(2000, 0, 1, 2, 3, 4, 6)});
|
||||
await Dates.create({date: new Date(2000, 0, 1, 2, 3, 4, 7)});
|
||||
let date = await Dates.findOne({
|
||||
order: [
|
||||
['date', 'ASC'],
|
||||
],
|
||||
});
|
||||
assert.strictEqual(date.date.getTime(), new Date(2000, 0, 1, 2, 3, 4, 5).getTime());
|
||||
assert.strictEqual(date.date.getTime(), dateCreate.date.getTime());
|
||||
|
||||
// Otherwise it hangs for 10 seconds, it seems that it keeps the connection alive.
|
||||
// https://stackoverflow.com/questions/28253831/recreating-database-sequelizejs-is-slow
|
||||
// https://github.com/sequelize/sequelize/issues/8468
|
||||
await sequelize.close();
|
||||
})();
|
||||
@ -1,110 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// https://stackoverflow.com/questions/17708620/sequelize-changing-model-schema-on-production
|
||||
|
||||
const assert = require('assert');
|
||||
const path = require('path');
|
||||
|
||||
const { Sequelize, DataTypes } = require('sequelize');
|
||||
|
||||
(async () => {
|
||||
{
|
||||
const sequelize = new Sequelize({
|
||||
dialect: 'sqlite',
|
||||
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
|
||||
});
|
||||
const IntegerNames = sequelize.define('IntegerNames', {
|
||||
value: { type: DataTypes.INTEGER, },
|
||||
name: { type: DataTypes.STRING, },
|
||||
}, {});
|
||||
await IntegerNames.sync({force: true})
|
||||
await IntegerNames.create({value: 2, name: 'two'});
|
||||
await IntegerNames.create({value: 3, name: 'three'});
|
||||
await sequelize.close();
|
||||
}
|
||||
|
||||
// Alter by adding column..
|
||||
{
|
||||
const sequelize = new Sequelize({
|
||||
dialect: 'sqlite',
|
||||
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
|
||||
});
|
||||
const IntegerNames = sequelize.define('IntegerNames', {
|
||||
value: { type: DataTypes.INTEGER, },
|
||||
name: { type: DataTypes.STRING, },
|
||||
nameEs: { type: DataTypes.STRING, },
|
||||
}, {});
|
||||
await IntegerNames.sync({alter: true})
|
||||
await IntegerNames.create({value: 5, name: 'five' , nameEs: 'cinco'});
|
||||
await IntegerNames.create({value: 7, name: 'seven', nameEs: 'siete'});
|
||||
const integerNames = await IntegerNames.findAll({
|
||||
order: [['value', 'ASC']],
|
||||
});
|
||||
assert(integerNames[0].value === 2);
|
||||
assert(integerNames[0].name === 'two');
|
||||
assert(integerNames[0].nameEs === null);
|
||||
assert(integerNames[1].name === 'three');
|
||||
assert(integerNames[1].nameEs === null);
|
||||
assert(integerNames[2].name === 'five');
|
||||
assert(integerNames[2].nameEs === 'cinco');
|
||||
assert(integerNames[3].name === 'seven');
|
||||
assert(integerNames[3].nameEs === 'siete');
|
||||
await sequelize.close();
|
||||
}
|
||||
|
||||
// Alter by removing column. undefined instead of null,
|
||||
// because the values really aren't present in the database anymore.
|
||||
{
|
||||
const sequelize = new Sequelize({
|
||||
dialect: 'sqlite',
|
||||
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
|
||||
});
|
||||
const IntegerNames = sequelize.define('IntegerNames', {
|
||||
value: { type: DataTypes.INTEGER, },
|
||||
name: { type: DataTypes.STRING, },
|
||||
}, {});
|
||||
await IntegerNames.sync({alter: true})
|
||||
const integerNames = await IntegerNames.findAll({
|
||||
order: [['value', 'ASC']],
|
||||
});
|
||||
assert(integerNames[0].value === 2);
|
||||
assert(integerNames[0].name === 'two');
|
||||
assert(integerNames[0].nameEs === undefined);
|
||||
assert(integerNames[1].name === 'three');
|
||||
assert(integerNames[1].nameEs === undefined);
|
||||
assert(integerNames[2].name === 'five');
|
||||
assert(integerNames[2].nameEs === undefined);
|
||||
assert(integerNames[3].name === 'seven');
|
||||
assert(integerNames[3].nameEs === undefined);
|
||||
await sequelize.close();
|
||||
}
|
||||
|
||||
// Alter a type.
|
||||
// Hmm, docs suggest data would get dropped, but I only see typecast without alter.drop,
|
||||
// so shy does it work still?. sqlite from CLI does confirm that it is now a VARCHAR(255)
|
||||
// column.
|
||||
{
|
||||
const sequelize = new Sequelize({
|
||||
dialect: 'sqlite',
|
||||
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
|
||||
});
|
||||
const IntegerNames = sequelize.define('IntegerNames', {
|
||||
value: { type: DataTypes.STRING, },
|
||||
name: { type: DataTypes.STRING, },
|
||||
}, {});
|
||||
await IntegerNames.sync({alter: true})
|
||||
const integerNames = await IntegerNames.findAll({
|
||||
order: [['value', 'ASC']],
|
||||
});
|
||||
assert(integerNames[0].value === '2');
|
||||
assert(integerNames[0].name === 'two');
|
||||
assert(integerNames[1].value === '3');
|
||||
assert(integerNames[1].name === 'three');
|
||||
assert(integerNames[2].value === '5');
|
||||
assert(integerNames[2].name === 'five');
|
||||
assert(integerNames[3].value === '7');
|
||||
assert(integerNames[3].name === 'seven');
|
||||
await sequelize.close();
|
||||
}
|
||||
|
||||
})();
|
||||
@ -1,36 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// https://stackoverflow.com/questions/39765582/in-sequelize-model-destroy-truncate-true-does-not-reset-primary-key
|
||||
|
||||
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 () => {
|
||||
const IntegerNames = sequelize.define('IntegerNames', {
|
||||
value: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
},
|
||||
}, {})
|
||||
await IntegerNames.sync({force: true})
|
||||
await IntegerNames.create({value: 2, name: 'two'})
|
||||
await IntegerNames.create({value: 3, name: 'three'})
|
||||
console.error((await IntegerNames.findOne({where: {value: 2}})).id)
|
||||
await IntegerNames.truncate({cascade: true})
|
||||
await IntegerNames.create({value: 5, name: 'five'})
|
||||
await IntegerNames.create({value: 7, name: 'seven'})
|
||||
console.error((await IntegerNames.findOne({where: {value: 5}})).id)
|
||||
|
||||
await sequelize.close()
|
||||
})();
|
||||
@ -1,86 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// https://stackoverflow.com/questions/54898994/bulkupdate-in-sequelize-orm/69044138#69044138
|
||||
|
||||
const assert = require('assert');
|
||||
const path = require('path');
|
||||
|
||||
const { Sequelize, DataTypes, Op } = require('sequelize');
|
||||
|
||||
const sequelize = new Sequelize({
|
||||
dialect: 'sqlite',
|
||||
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
|
||||
});
|
||||
|
||||
(async () => {
|
||||
const Inverses = sequelize.define('Inverses',
|
||||
{
|
||||
value: {
|
||||
type: DataTypes.INTEGER,
|
||||
primaryKey: true,
|
||||
},
|
||||
inverse: {
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
},
|
||||
},
|
||||
{ timestamps: false }
|
||||
);
|
||||
await Inverses.sync({force: true})
|
||||
await Inverses.create({value: 2, inverse: -2, name: 'two'});
|
||||
await Inverses.create({value: 3, inverse: -3, name: 'three'});
|
||||
await Inverses.create({value: 5, inverse: -5, name: 'five'});
|
||||
|
||||
// Initial state.
|
||||
assert.strictEqual((await Inverses.findOne({ where: { value: 2 } })).inverse, -2);
|
||||
assert.strictEqual((await Inverses.findOne({ where: { value: 3 } })).inverse, -3);
|
||||
assert.strictEqual((await Inverses.findOne({ where: { value: 5 } })).inverse, -5);
|
||||
assert.strictEqual((await Inverses.findOne({ where: { value: 2 } })).name, 'two');
|
||||
assert.strictEqual((await Inverses.findOne({ where: { value: 3 } })).name, 'three');
|
||||
assert.strictEqual((await Inverses.findOne({ where: { value: 5 } })).name, 'five');
|
||||
assert.strictEqual(await Inverses.count(), 3);
|
||||
|
||||
// Update to fixed value.
|
||||
await Inverses.update(
|
||||
{ inverse: 0, },
|
||||
{ where: { value: { [Op.gt]: 2 } } },
|
||||
);
|
||||
assert.strictEqual((await Inverses.findOne({ where: { value: 2 } })).inverse, -2);
|
||||
assert.strictEqual((await Inverses.findOne({ where: { value: 3 } })).inverse, 0);
|
||||
assert.strictEqual((await Inverses.findOne({ where: { value: 5 } })).inverse, 0);
|
||||
assert.strictEqual(await Inverses.count(), 3);
|
||||
|
||||
// Update to match another column.
|
||||
await Inverses.update(
|
||||
{ inverse: sequelize.col('value'), },
|
||||
{ where: { value: { [Op.gt]: 2 } } },
|
||||
);
|
||||
assert.strictEqual((await Inverses.findOne({ where: { value: 2 } })).inverse, -2);
|
||||
assert.strictEqual((await Inverses.findOne({ where: { value: 3 } })).inverse, 3);
|
||||
assert.strictEqual((await Inverses.findOne({ where: { value: 5 } })).inverse, 5);
|
||||
assert.strictEqual(await Inverses.count(), 3);
|
||||
|
||||
// Update to match another column with modification.
|
||||
await Inverses.update(
|
||||
{ inverse: sequelize.fn('1 + ', sequelize.col('value')), },
|
||||
{ where: { value: { [Op.gt]: 2 } } },
|
||||
);
|
||||
assert.strictEqual((await Inverses.findOne({ where: { value: 2 } })).inverse, -2);
|
||||
assert.strictEqual((await Inverses.findOne({ where: { value: 3 } })).inverse, 4);
|
||||
assert.strictEqual((await Inverses.findOne({ where: { value: 5 } })).inverse, 6);
|
||||
assert.strictEqual(await Inverses.count(), 3);
|
||||
|
||||
// A string function test.
|
||||
await Inverses.update(
|
||||
{ name: sequelize.fn('upper', sequelize.col('name')), },
|
||||
{ where: { value: { [Op.gt]: 2 } } },
|
||||
);
|
||||
assert.strictEqual((await Inverses.findOne({ where: { value: 2 } })).name, 'two');
|
||||
assert.strictEqual((await Inverses.findOne({ where: { value: 3 } })).name, 'THREE');
|
||||
assert.strictEqual((await Inverses.findOne({ where: { value: 5 } })).name, 'FIVE');
|
||||
assert.strictEqual(await Inverses.count(), 3);
|
||||
|
||||
await sequelize.close();
|
||||
})();
|
||||
@ -1,69 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// https://stackoverflow.com/questions/54898994/bulkupdate-in-sequelize-orm/69044138#69044138
|
||||
|
||||
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 () => {
|
||||
const Integer = sequelize.define('Integer',
|
||||
{
|
||||
value: {
|
||||
type: DataTypes.INTEGER,
|
||||
unique: true, // mandatory
|
||||
primaryKey: true,
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
},
|
||||
inverse: {
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: false,
|
||||
}
|
||||
);
|
||||
await Integer.sync({force: true})
|
||||
await Integer.create({value: 2, inverse: -2, name: 'two'});
|
||||
await Integer.create({value: 3, inverse: -3, name: 'three'});
|
||||
await Integer.create({value: 5, inverse: -5, name: 'five'});
|
||||
|
||||
// Initial state.
|
||||
assert.strictEqual((await Integer.findOne({ where: { value: 2 } })).name, 'two');
|
||||
assert.strictEqual((await Integer.findOne({ where: { value: 3 } })).name, 'three');
|
||||
assert.strictEqual((await Integer.findOne({ where: { value: 5 } })).name, 'five');
|
||||
assert.strictEqual((await Integer.findOne({ where: { value: 2 } })).inverse, -2);
|
||||
assert.strictEqual((await Integer.findOne({ where: { value: 3 } })).inverse, -3);
|
||||
assert.strictEqual((await Integer.findOne({ where: { value: 5 } })).inverse, -5);
|
||||
assert.strictEqual(await Integer.count(), 3);
|
||||
|
||||
// Update.
|
||||
await Integer.bulkCreate(
|
||||
[
|
||||
{value: 2, name: 'TWO'},
|
||||
{value: 3, name: 'THREE'},
|
||||
{value: 7, name: 'SEVEN'},
|
||||
],
|
||||
{ updateOnDuplicate: ["name"] }
|
||||
);
|
||||
|
||||
// Final state.
|
||||
assert.strictEqual((await Integer.findOne({ where: { value: 2 } })).name, 'TWO');
|
||||
assert.strictEqual((await Integer.findOne({ where: { value: 3 } })).name, 'THREE');
|
||||
assert.strictEqual((await Integer.findOne({ where: { value: 5 } })).name, 'five');
|
||||
assert.strictEqual((await Integer.findOne({ where: { value: 7 } })).name, 'SEVEN');
|
||||
assert.strictEqual((await Integer.findOne({ where: { value: 2 } })).inverse, -2);
|
||||
assert.strictEqual((await Integer.findOne({ where: { value: 3 } })).inverse, -3);
|
||||
assert.strictEqual((await Integer.findOne({ where: { value: 5 } })).inverse, -5);
|
||||
assert.strictEqual(await Integer.count(), 4);
|
||||
|
||||
await sequelize.close();
|
||||
})();
|
||||
Reference in New Issue
Block a user