Отношение один к одному указывает, что одна сущность может владеть другой сущностью в единственном экземпляре. Например, у пользователя может быть один аакаунт в каком-то сервисе. С другой стороны, один аккаунт может принадлежать только одному пользователю.
Для создания подобной связи между моделями применяется метод hasOne(). Например, определим модели пользователя и аккаунта:
const Sequelize = require("sequelize"); const sequelize = new Sequelize("game", "root", "123456", { dialect: "mysql", host: "localhost", define: { timestamps: false } }); const Coach = sequelize.define("coach", { id: { type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true, allowNull: false }, name: { type: Sequelize.STRING, allowNull: false } }); const Team = sequelize.define("team", { id: { type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true, allowNull: false }, name: { type: Sequelize.STRING, allowNull: false } }); Coach.hasOne(Team, { onDelete: "cascade"}); sequelize.sync({force:true}).then(()=>{ console.log("Tables have been created"); }).catch(err=>console.log(err));
В данном случае модель тренера (Coach) условно считается главной, а модель команды (Team) зависимой (но в данном случае деление на главную и зависимую модель
достаточно условно). Поэтому метод hasOne()
вызывается у модели Coach, и в качестве первого параметра передается модель Team. Хотя в данном случае не имеет значения, какая именно модель является главной или зависимой.
Второй параметр метода задает конфигурацию связи, в частности, каскадное удаление.
В итоге при выполнении данного кода в SQLite будут созданы следующие таблицы:
CREATE TABLE IF NOT EXISTS `users` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` VARCHAR(255) NOT NULL, `age` INTEGER NOT NULL ); CREATE TABLE IF NOT EXISTS `accounts` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT, `email` VARCHAR(255) NOT NULL, `userId` INTEGER REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE );
Как мы видим, в таблице accounts создается дополнительный столбец userId, через который данная таблица будет связана с таблицей users.
Для установки связанных данных применяется метод setНАЗВАНИЕ_МОДЕЛИ(). Например, добавим пользователя и его аккаунт:
// добавляем пользователя User.create({ name: "Tom", age: 39}) .then(user=>{ // Добавляем аккаунт Account.create({email: "tom@mimimail.com"}).then(account=>{ // устанавливаем для пользователя аккаунт user.setAccount(account).catch(err=>console.log(err)); }); }).catch(err=>console.log(err));
По факту метод setМОДЕЛЬ()
будет вызывать SQL-команду UPDATE. То есть к моменту вызова данного метода связываемые сущности уже должны быть в
базе данных.
Для получения связанных данных применяется метод getНАЗВАНИЕ_МОДЕЛИ(). Например, получим тренера и его команду:
// получаем пользователя с id=1 User.findByPk(1).then(user=>{ if(!user) return console.log("User not found"); user.getAccount().then(account=>{ console.log(user.name, "-", account.email); }); });
В данном случае на консоли мы получим:
Tom - tom@mimimail.com
Получение всех пользователей с включением связанных данных:
User.findAll({ attributes: ["name"], // включаем столбец name из таблицы users include: [{ model: Account, attributes: ["email"] // включаем столбец name из таблицы accounts }] }).then(users => { for(user of users){ console.log(user.name, "-", user.account.email); } });