Отношение один к одному указывает, что одна сущность может владеть другой сущностью в единственном экземпляре. Например, у пользователя может быть один аакаунт в каком-то сервисе. С другой стороны, один аккаунт может принадлежать только одному пользователю.
Для создания подобной связи между моделями применяется метод 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);
}
});