├── .DS_Store ├── readme_assets ├── 1.png └── 2.png ├── .sequelizerc ├── package.json ├── config └── config.json ├── db ├── models │ ├── dogscats.js │ ├── cat.js │ ├── dog.js │ ├── post.js │ ├── user.js │ └── index.js ├── migrations │ ├── 20210923115314-create-dog.js │ ├── 20210923115627-create-cat.js │ ├── 20210722122447-new_column_in_user.js │ ├── 20210721065603-create-user.js │ ├── 20210721072931-create-post.js │ └── 20210923115842-create-dogscats.js └── seeders │ ├── 20210721081426-post.js │ └── 20210721075320-user.js ├── app.js ├── appMany.js ├── .gitignore └── README.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jtarasova/sequelize_intro/HEAD/.DS_Store -------------------------------------------------------------------------------- /readme_assets/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jtarasova/sequelize_intro/HEAD/readme_assets/1.png -------------------------------------------------------------------------------- /readme_assets/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jtarasova/sequelize_intro/HEAD/readme_assets/2.png -------------------------------------------------------------------------------- /.sequelizerc: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | 'config': path.resolve('config', 'config.json'), 5 | 'models-path': path.resolve('db', 'models'), 6 | 'seeders-path': path.resolve('db', 'seeders'), 7 | 'migrations-path': path.resolve('db', 'migrations') 8 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "p1w3w3", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node app.js", 8 | "up": "npx sequelize-cli db:migrate", 9 | "down": "sequelize-cli db:migrate:undo", 10 | "many": "NODE_ENV=test node appMany.js" 11 | }, 12 | "keywords": [], 13 | "author": "", 14 | "license": "ISC", 15 | "dependencies": { 16 | "pg": "^8.6.0", 17 | "pg-hstore": "^2.3.4", 18 | "sequelize": "^6.6.5" 19 | }, 20 | "devDependencies": { 21 | "sequelize-cli": "^6.2.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /config/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "development": { 3 | "username": "elbrus_user", 4 | "password": "123", 5 | "database": "elbrus", 6 | "host": "127.0.0.1", 7 | "dialect": "postgres", 8 | "seederStorage": "sequelize", 9 | "seederStorageTableName": "SequelizeData" 10 | }, 11 | "test": { 12 | "username": "jora", 13 | "password": "123", 14 | "database": "party", 15 | "host": "127.0.0.1", 16 | "dialect": "postgres" 17 | }, 18 | "production": { 19 | "username": "elbrus_user", 20 | "password": "123", 21 | "database": "elbrus", 22 | "host": "127.0.0.1", 23 | "dialect": "postgres" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /db/models/dogscats.js: -------------------------------------------------------------------------------- 1 | const { Model } = require('sequelize'); 2 | 3 | module.exports = (sequelize, DataTypes) => { 4 | class Dogscats extends Model { 5 | /** 6 | * Helper method for defining associations. 7 | * This method is not a part of Sequelize lifecycle. 8 | * The `models/index` file will call this method automatically. 9 | */ 10 | static associate(models) { 11 | // define association here 12 | } 13 | } 14 | Dogscats.init( 15 | { 16 | dog_id: DataTypes.INTEGER, 17 | cat_id: DataTypes.INTEGER, 18 | }, 19 | { 20 | sequelize, 21 | modelName: 'Dogscats', 22 | } 23 | ); 24 | return Dogscats; 25 | }; 26 | -------------------------------------------------------------------------------- /db/migrations/20210923115314-create-dog.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | up: async (queryInterface, Sequelize) => { 3 | await queryInterface.createTable('Dogs', { 4 | id: { 5 | allowNull: false, 6 | autoIncrement: true, 7 | primaryKey: true, 8 | type: Sequelize.INTEGER, 9 | }, 10 | name: { 11 | type: Sequelize.STRING(50), 12 | allowNull: false, 13 | }, 14 | age: Sequelize.INTEGER, 15 | createdAt: { 16 | allowNull: false, 17 | type: Sequelize.DATE, 18 | }, 19 | updatedAt: { 20 | allowNull: false, 21 | type: Sequelize.DATE, 22 | }, 23 | }); 24 | }, 25 | down: async (queryInterface, Sequelize) => { 26 | await queryInterface.dropTable('Dogs'); 27 | }, 28 | }; 29 | -------------------------------------------------------------------------------- /db/migrations/20210923115627-create-cat.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | up: async (queryInterface, Sequelize) => { 3 | await queryInterface.createTable('Cats', { 4 | id: { 5 | allowNull: false, 6 | autoIncrement: true, 7 | primaryKey: true, 8 | type: Sequelize.INTEGER, 9 | }, 10 | name: { 11 | type: Sequelize.STRING(50), 12 | allowNull: false, 13 | }, 14 | age: Sequelize.INTEGER, 15 | createdAt: { 16 | allowNull: false, 17 | type: Sequelize.DATE, 18 | }, 19 | updatedAt: { 20 | allowNull: false, 21 | type: Sequelize.DATE, 22 | }, 23 | }); 24 | }, 25 | down: async (queryInterface, Sequelize) => { 26 | await queryInterface.dropTable('Cats'); 27 | }, 28 | }; 29 | -------------------------------------------------------------------------------- /db/models/cat.js: -------------------------------------------------------------------------------- 1 | const { Model } = require('sequelize'); 2 | 3 | module.exports = (sequelize, DataTypes) => { 4 | class Cat extends Model { 5 | /** 6 | * Helper method for defining associations. 7 | * This method is not a part of Sequelize lifecycle. 8 | * The `models/index` file will call this method automatically. 9 | */ 10 | static associate({ Dog }) { 11 | // define association here 12 | this.belongsToMany(Dog, { through: 'Dogscats', foreignKey: 'cat_id' }); 13 | } 14 | } 15 | Cat.init( 16 | { 17 | name: { 18 | type: DataTypes.STRING(50), 19 | allowNull: false, 20 | }, 21 | age: DataTypes.INTEGER, 22 | }, 23 | { 24 | sequelize, 25 | modelName: 'Cat', 26 | } 27 | ); 28 | return Cat; 29 | }; 30 | -------------------------------------------------------------------------------- /db/models/dog.js: -------------------------------------------------------------------------------- 1 | const { Model } = require('sequelize'); 2 | 3 | module.exports = (sequelize, DataTypes) => { 4 | class Dog extends Model { 5 | /** 6 | * Helper method for defining associations. 7 | * This method is not a part of Sequelize lifecycle. 8 | * The `models/index` file will call this method automatically. 9 | */ 10 | static associate({ Cat }) { 11 | // define association here 12 | this.belongsToMany(Cat, { through: 'Dogscats', foreignKey: 'dog_id' }); 13 | } 14 | } 15 | Dog.init( 16 | { 17 | name: { 18 | type: DataTypes.STRING(50), 19 | allowNull: false, 20 | }, 21 | age: DataTypes.INTEGER, 22 | }, 23 | { 24 | sequelize, 25 | modelName: 'Dog', 26 | } 27 | ); 28 | return Dog; 29 | }; 30 | -------------------------------------------------------------------------------- /db/migrations/20210722122447-new_column_in_user.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | up: async (queryInterface, Sequelize) => { 5 | await queryInterface.addColumn( 6 | 'Users', // table name 7 | 'age', // new field name 8 | { 9 | type: Sequelize.INTEGER, 10 | allowNull: true, 11 | } 12 | ); 13 | 14 | /** 15 | * Add altering commands here. 16 | * 17 | * Example: 18 | * await queryInterface.createTable('users', { id: Sequelize.INTEGER }); 19 | */ 20 | }, 21 | 22 | down: async (queryInterface, Sequelize) => { 23 | await queryInterface.removeColumn('Users', 'age'); 24 | 25 | /** 26 | * Add reverting commands here. 27 | * 28 | * Example: 29 | * await queryInterface.dropTable('users'); 30 | */ 31 | }, 32 | }; 33 | -------------------------------------------------------------------------------- /db/migrations/20210721065603-create-user.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | module.exports = { 3 | up: async (queryInterface, Sequelize) => { 4 | await queryInterface.createTable('Users', { 5 | id: { 6 | allowNull: false, 7 | autoIncrement: true, 8 | primaryKey: true, 9 | type: Sequelize.INTEGER, 10 | }, 11 | name: { 12 | type: Sequelize.STRING, 13 | allowNull: false, 14 | unique: true, 15 | }, 16 | email: { 17 | type: Sequelize.STRING, 18 | allowNull: false, 19 | unique: true, 20 | }, 21 | createdAt: { 22 | allowNull: false, 23 | type: Sequelize.DATE, 24 | }, 25 | updatedAt: { 26 | allowNull: false, 27 | type: Sequelize.DATE, 28 | }, 29 | }); 30 | }, 31 | down: async (queryInterface, Sequelize) => { 32 | await queryInterface.dropTable('Users'); 33 | }, 34 | }; 35 | -------------------------------------------------------------------------------- /db/models/post.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const { Model } = require('sequelize'); 3 | module.exports = (sequelize, DataTypes) => { 4 | class Post extends Model { 5 | /** 6 | * Helper method for defining associations. 7 | * This method is not a part of Sequelize lifecycle. 8 | * The `models/index` file will call this method automatically. 9 | */ 10 | static associate(models) { 11 | this.belongsTo(models.User, { 12 | foreignKey: 'author', 13 | }); // описываем связь с моедлью юзеров через внешний ключ 14 | } 15 | } 16 | Post.init( 17 | { 18 | body: { 19 | type: DataTypes.TEXT, 20 | allowNull: false, 21 | }, 22 | author: { // НЕ ЗАБУДЬ ДОБАВИТЬ ЭТО В МИГРАЦИЮ!!! 23 | type: DataTypes.INTEGER, 24 | allowNull: false, 25 | }, 26 | }, 27 | { 28 | sequelize, 29 | modelName: 'Post', 30 | } 31 | ); 32 | return Post; 33 | }; 34 | -------------------------------------------------------------------------------- /db/seeders/20210721081426-post.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | up: async (queryInterface, Sequelize) => { 5 | /** 6 | * Add seed commands here. 7 | * 8 | * Example: **/ 9 | 10 | await queryInterface.bulkInsert( 11 | 'Posts', 12 | [ 13 | { 14 | body: 'WHYYYYY', 15 | author: 1, 16 | createdAt: new Date(), // в seeder'ах нужно добавлять это руками 17 | updatedAt: new Date(), 18 | }, 19 | { 20 | body: 'WHEEEEEERREEEE', 21 | author: 3, 22 | createdAt: new Date(), 23 | updatedAt: new Date(), 24 | }, 25 | ], 26 | {} 27 | ); 28 | }, 29 | 30 | down: async (queryInterface, Sequelize) => { 31 | /** 32 | * Add commands to revert seed here. 33 | * 34 | * Example: 35 | */ 36 | 37 | await queryInterface.bulkDelete('Posts', null, {}); 38 | }, 39 | }; 40 | -------------------------------------------------------------------------------- /db/migrations/20210721072931-create-post.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | module.exports = { 3 | up: async (queryInterface, Sequelize) => { 4 | await queryInterface.createTable('Posts', { 5 | id: { 6 | allowNull: false, 7 | autoIncrement: true, 8 | primaryKey: true, 9 | type: Sequelize.INTEGER, 10 | }, 11 | body: { 12 | type: Sequelize.TEXT, 13 | allowNull: false, 14 | }, 15 | author: { 16 | type: Sequelize.INTEGER, 17 | allowNull: false, 18 | references: { 19 | model: { 20 | tableName: 'Users', 21 | }, 22 | key: 'id', 23 | }, 24 | }, 25 | createdAt: { 26 | allowNull: false, 27 | type: Sequelize.DATE, 28 | }, 29 | updatedAt: { 30 | allowNull: false, 31 | type: Sequelize.DATE, 32 | }, 33 | }); 34 | }, 35 | down: async (queryInterface, Sequelize) => { 36 | await queryInterface.dropTable('Posts'); 37 | }, 38 | }; 39 | -------------------------------------------------------------------------------- /db/migrations/20210923115842-create-dogscats.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | up: async (queryInterface, Sequelize) => { 3 | await queryInterface.createTable('Dogscats', { 4 | id: { 5 | allowNull: false, 6 | autoIncrement: true, 7 | primaryKey: true, 8 | type: Sequelize.INTEGER, 9 | }, 10 | dog_id: { 11 | type: Sequelize.INTEGER, 12 | references: { 13 | model: 'Dogs', // tableName 14 | key: 'id', 15 | }, 16 | }, 17 | cat_id: { 18 | type: Sequelize.INTEGER, 19 | references: { 20 | model: 'Cats', // tableName 21 | key: 'id', 22 | }, 23 | }, 24 | createdAt: { 25 | allowNull: false, 26 | type: Sequelize.DATE, 27 | }, 28 | updatedAt: { 29 | allowNull: false, 30 | type: Sequelize.DATE, 31 | }, 32 | }); 33 | }, 34 | down: async (queryInterface, Sequelize) => { 35 | await queryInterface.dropTable('Dogscats'); 36 | }, 37 | }; 38 | -------------------------------------------------------------------------------- /db/models/user.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const { Model } = require('sequelize'); 3 | module.exports = (sequelize, DataTypes) => { 4 | class User extends Model { 5 | /** 6 | * Helper method for defining associations. 7 | * This method is not a part of Sequelize lifecycle. 8 | * The `models/index` file will call this method automatically. 9 | */ 10 | static associate(models) { 11 | this.hasMany(models.Post, { 12 | foreignKey: 'author', // описываем связь с моедлью юзеров через внешний ключ 13 | }); 14 | } 15 | } 16 | User.init( 17 | { 18 | name: { 19 | type: DataTypes.STRING, 20 | allowNull: false, 21 | unique: true, 22 | }, 23 | email: { 24 | type: DataTypes.STRING, 25 | allowNull: false, 26 | unique: true, 27 | }, 28 | age: { 29 | type: DataTypes.INTEGER, 30 | allowNull: true, 31 | }, 32 | }, 33 | { 34 | sequelize, 35 | modelName: 'User', 36 | } 37 | ); 38 | return User; 39 | }; 40 | -------------------------------------------------------------------------------- /db/seeders/20210721075320-user.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | up: async (queryInterface, Sequelize) => { 5 | /** 6 | * Add seed commands here. 7 | * 8 | * Example: 9 | * await queryInterface.bulkInsert('People', [{ 10 | * name: 'John Doe', 11 | * isBetaMember: false 12 | * }], {}); 13 | */ 14 | 15 | await queryInterface.bulkInsert( 16 | 'Users', 17 | [ 18 | { 19 | name: 'John Doe', 20 | email: 'bla@bla.bla', 21 | createdAt: new Date(), 22 | updatedAt: new Date(), 23 | }, 24 | { 25 | name: 'Jane Doe', 26 | email: 'bla2@bla.bla', 27 | createdAt: new Date(), 28 | updatedAt: new Date(), 29 | }, 30 | { 31 | name: 'George Bla', 32 | email: 'george@bla.bla', 33 | createdAt: new Date(), 34 | updatedAt: new Date(), 35 | }, 36 | ], 37 | {} 38 | ); 39 | }, 40 | 41 | down: async (queryInterface, Sequelize) => { 42 | /** 43 | * Add commands to revert seed here. 44 | * 45 | * Example: 46 | */ 47 | await queryInterface.bulkDelete('Users', null, {}); 48 | }, 49 | }; 50 | -------------------------------------------------------------------------------- /db/models/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const Sequelize = require('sequelize'); 6 | const basename = path.basename(__filename); 7 | const env = process.env.NODE_ENV || 'development'; 8 | const config = require(__dirname + '/../../config/config.json')[env]; 9 | const db = {}; 10 | 11 | let sequelize; 12 | if (config.use_env_variable) { 13 | sequelize = new Sequelize(process.env[config.use_env_variable], config); 14 | } else { 15 | sequelize = new Sequelize( 16 | config.database, 17 | config.username, 18 | config.password, 19 | config 20 | ); 21 | } 22 | 23 | fs.readdirSync(__dirname) 24 | .filter((file) => { 25 | return ( 26 | file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js' 27 | ); 28 | }) 29 | .forEach((file) => { 30 | const model = require(path.join(__dirname, file))( 31 | sequelize, 32 | Sequelize.DataTypes 33 | ); 34 | db[model.name] = model; 35 | }); 36 | 37 | Object.keys(db).forEach((modelName) => { 38 | if (db[modelName].associate) { 39 | db[modelName].associate(db); 40 | } 41 | }); 42 | 43 | db.sequelize = sequelize; 44 | db.Sequelize = Sequelize; 45 | 46 | module.exports = db; 47 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | // console.log('hello'); 2 | const db = require('./db/models'); 3 | const { 4 | Sequelize: { Op }, 5 | User, 6 | sequelize, 7 | } = db; 8 | 9 | const main = async () => { 10 | await sequelize.authenticate(); 11 | console.log('Connection has been established successfully.'); 12 | const usr = await User.create({ name: 'Igoro', email: 'in@mailo.ru' }); 13 | // console.log(usr.dataValues); 14 | // const allUsers = await User.findAll({ 15 | // where: { name: 'George Bla' }, 16 | // raw: true, 17 | // }); 18 | // // console.log(allUsers); 19 | // let d1 = new Date(2021, 06, 22); 20 | // let d2 = new Date(2021, 06, 21); 21 | // console.log(d1); 22 | // let a = await User.findAll({ 23 | // attributes: ['name', 'email'], 24 | // where: { 25 | // createdAt: { 26 | // [Op.between]: [d2, d1], 27 | // }, 28 | // }, 29 | // raw: true, 30 | // }); 31 | // console.log(a); 32 | 33 | // let a = await User.findOne({ where: { name: 'George Bla' }, raw: true }); 34 | // let b = await User.findAll({ where: { name: 'George Bla' }, raw: true }); 35 | // a.email = 'george@blahh.bla'; 36 | // await a.save(); 37 | // console.log(a); 38 | // console.log(b); 39 | }; 40 | 41 | // main(); 42 | -------------------------------------------------------------------------------- /appMany.js: -------------------------------------------------------------------------------- 1 | const db = require('./db/models'); 2 | const { 3 | Sequelize: { Op }, 4 | sequelize, 5 | Cat, 6 | Dog, 7 | Dogscats, 8 | } = db; 9 | 10 | const manyMain = async () => { 11 | // await Cat.create({ name: 'Lol', age: 9 }); 12 | // await Cat.create({ name: 'Lil', age: 2 }); 13 | // await Cat.create({ name: 'Lal', age: 4 }); 14 | // await Dog.create({ name: 'Bob', age: 3 }); 15 | // await Dog.create({ name: 'Beb', age: 12 }); 16 | // await Dog.create({ name: 'Bib', age: 8 }); 17 | // const bob = await Dog.findOne({ 18 | // where: { name: 'Bob' }, 19 | // // attributes: ['id'], 20 | // // raw: true, 21 | // }); 22 | // const lol = await Cat.findOne({ 23 | // where: { name: 'Lol' }, 24 | // // attributes: ['id'], 25 | // raw: true, 26 | // }); 27 | // await Dogscats.create({ dog_id: bob.id, cat_id: lol.id }); 28 | // await Dogscats.create({ dog_id: 3, cat_id: 2 }); 29 | // await Dogscats.create({ dog_id: 2, cat_id: 2 }); 30 | const catsWithFriends = await Cat.findAll({ 31 | include: { 32 | model: Dog, 33 | attributes: ['name', 'age'], 34 | through: { 35 | model: Dogscats, 36 | attributes: [], 37 | }, 38 | }, 39 | order: [['age', 'DESC']], 40 | raw: true, 41 | }); 42 | catsWithFriends.map((el) => console.log(el)); 43 | // const catsWithFriends = await Cat.findAll({ 44 | // order: [[Dog, 'age', 'ASC']], 45 | // include: [Dog], 46 | // raw: true, 47 | // }); 48 | // console.log(catsWithFriends); 49 | // const a = await Cat.findAll({ 50 | // where: { 51 | // age: { 52 | // [Op.gte]: 4, 53 | // }, 54 | // }, 55 | // }); 56 | // console.log(a); 57 | }; 58 | 59 | manyMain(); 60 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | 106 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sequelize intro 2 | 3 | ## Как начинали работу 4 | 5 | 1. `npm init -y` - инициализируем проект node 6 | 1. `npm i sequelize pg pg-hstore` - устанавливаем зависимости postgres 7 | 1. `npm i -D sequelize-cli` - устанавливаем sequelize cli 8 | 1. создаём файл `.sequelizerc`: 9 | 10 | ```Javascript 11 | const path = require('path'); 12 | module.exports = { 13 | 'config': path.resolve('config', 'config.json'), 14 | 'models-path': path.resolve('db', 'models'), 15 | 'seeders-path': path.resolve('db', 'seeders'), 16 | 'migrations-path': path.resolve('db', 'migrations') 17 | }; 18 | ``` 19 | 20 | 1. `npx sequelize-cli init` - создаём структуру для работы с sequelize 21 | 1. В файле `config.json` изменили данные для БД (username, password, database, dialect) на свои. Обратите внимание, что мы ввели разные данные для development и test 22 | 1. Для того, чтобы sequelize следил за сидерами (не накатывались те сидеры, которые уже были добавлены в БД, аналогично миграциям),в файл `config.json` добавили строчки 23 | 24 | ``` 25 | "seederStorage": "sequelize", 26 | "seederStorageTableName": "SequelizeData" 27 | ``` 28 | 29 | ## Что сделали 30 | 31 | 1. Создали модель командой `npx sequelize-cli model:generate --name User --attributes firstName:string,lastName:string,email:string` (изменили под себя) 32 | - Одновременно с этим создалась миграция 33 | - **Если поменяли что-то в модели - меняем и в миграции** 34 | 1. Накатили миграцию `npx sequelize-cli db:migrate` 35 | 1. Создали seeder командой `npx sequelize-cli seed:generate --name demo-user` (изменили под себя) 36 | 37 | ## На что обратить внимание 38 | 39 | 1. Когда пишем seeder, поля `createdAt` и `updatedAt` нужно заполнить самому `new Date()` 40 | 41 | ### Связи 42 | 43 | **_Важно_** 44 | 45 | Если в миграции вы указываете, что какое-то поле _таблицы А_ ссылается на _Таблицу В_, то на момент накатывания миграции с _Таблицей А_, уже должна существовать _Таблица В_. В обратном случае, вы получите ошибку `Table_name is not exist`. 46 | 47 | ![One-to-Many relation](readme_assets/1.png) 48 | _Таблица 1_. Связь One-to-Many. 49 | 50 | 1. Чтобы создать связь (один ко многим), нужно: 51 | 52 | - в модели `Post`: 53 | 54 | ```JavaScript 55 | static associate(models) { 56 | this.belongsTo(models.User, { 57 | foreignKey: 'author', 58 | }); 59 | } 60 | ``` 61 | 62 | - в модели `User`: 63 | 64 | ```JavaScript 65 | static associate(models) { 66 | this.hasMany(models.Post, { 67 | foreignKey: 'author', 68 | }); 69 | } 70 | ``` 71 | 72 | - в миграции `create-post`: 73 | 74 | ```JavaScript 75 | author: { 76 | type: Sequelize.INTEGER, 77 | allowNull: false, 78 | references: { 79 | model: { 80 | tableName: 'Users', 81 | }, 82 | key: 'id', 83 | }, 84 | } 85 | ``` 86 | 87 | ## Миграции 88 | 89 | Чтобы добвить новое поле в таблицу, нужно: 90 | 91 | 1. Создать миграцию командой `npx sequelize-cli migration:create --name new_column_in_user` 92 | 93 | 1. Изменить миграцию с использованием 94 | 95 | `JavaScript queryInterface.addColumn ` 96 | 97 | и 98 | 99 | `queryInterface.removeColumn` 100 | 101 | 1. Добавить новое поле в модель `User` 102 | 1. Запустить миграцию `npx sequelize-cli db:migrate` 103 | 104 | 105 | ## Many to many 106 | 107 | Для этого примера создан отдельный файл `appMany.js`, и отдельная бд, которая описана в файле config.json в части test. Чтобы запустить этот файл, нужно воспользоваться скриптом `npm run many` 108 | 109 | ### Идея 110 | 111 | Есть три таблицы: Dogs, Cats и DogsCats. Многие собаки могут дружить с многими кошками. Связь между кошками и собаками описывается в таблице `Dogscats`. 112 | 113 | ![Many-to-Many relation](readme_assets/2.png) 114 | _Таблица 1_. Связь Many-to-Many. 115 | 116 | ### Модели 117 | 118 | 1. В модели Dogs нужно описать связь с многими котами через промежуточную таблицу: 119 | 120 | ```Javascript 121 | this.belongsToMany(Cat, { through: 'Dogscats', foreignKey: 'dog_id' }); 122 | ``` 123 | 124 | 1. В модели Cats нужно сделать аналогичную связь: 125 | 126 | ```Javascript 127 | this.belongsToMany(Dog, { through: 'Dogscats', foreignKey: 'cat_id' }); 128 | ``` 129 | 130 | 1. В модели Dogscats _ничего делать не нужно_ 131 | 132 | ### Миграции 133 | 134 | 1. В миграции `dogscats` указываем, что столбцы `cat_id` и `dog_id` ссылаются на таблицы `Cats` и `Dog` соответсвенно 135 | 136 | ```Javascript 137 | dog_id: { 138 | type: Sequelize.INTEGER, 139 | references: { 140 | model: 'Dogs', // tableName 141 | key: 'id', 142 | }, 143 | }, 144 | cat_id: { 145 | type: Sequelize.INTEGER, 146 | references: { 147 | model: 'Cats', // tableName 148 | key: 'id', 149 | }, 150 | }, 151 | ``` 152 | 153 | 1. В миграциях `Cats` и `Dogs` ничего делать не нужно 154 | --------------------------------------------------------------------------------