Связь один-к-одному

Последнее обновление: 24.11.2023

Отношение один к одному указывает, что одна сущность может владеть другой сущностью в единственном экземпляре. Например, у пользователя может быть один аакаунт в каком-то сервисе. С другой стороны, один аккаунт может принадлежать только одному пользователю.

Для создания подобной связи между моделями применяется метод 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);
      }
});
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850