1.42M
Категория: ПрограммированиеПрограммирование

Связь Many -To - Many

1.

фаза 1 · неделя 3 · день 3
Many-To-Many
Seeders

2.

План
1. Связь Many-To-Many
2. Наполнение БД (Seeders)

3.

Many-To-Many

4.

Many-To-Many
Для создания связи Many-To-Many должна использоваться промежуточная
таблица. В примере создана промежуточная таблица Posts_tags, которая
содержит в себе внешние ключи на таблицы Posts и Tags.

5.

Миграции
В миграции необходимо прописать references для таблиц, которые необходимо связать.
В таблице Posts_tags для атрибутов post_id и tag_id указываем references на
соответствующие таблицы:
post_id: {
tag_id: {
type: Sequelize.INTEGER,
type: Sequelize.INTEGER,
references: {
references: {
model: 'Posts', // tableName
model: 'Tags', // tableName
key: 'id',
key: 'id',
}
}
}
}

6.

Описание моделей
Далее нужно прописать associate в моделях. Есть 3 способа описать связь Many-To-Many:
● Связь через промежуточную таблицу
Можно обратиться к Posts и/или Tags и include их между собой
Нельзя обратиться к промежуточной и сделать include
● Две связи один ко многим
Можно обратиться к Posts или Tags и include промежуточную
Можно обратиться к промежуточной и include Posts и/или Tags
Нельзя include Posts и Tags напрямую
● Комбинировать эти два подхода
Можно всё :)

7.

Связь через промежуточную таблицу
// Model Post
static associate(models) {
this.belongsToMany(models.Tag, { through: 'Posts_tag', foreignKey:
'post_id' })
}
// Model Tag
static associate(models) {
this.belongsToMany(models.Post, { through: 'Posts_tag', foreignKey:
'tag_id' })
}
В модели Posts_tag ничего не указываем.

8.

Связь через промежуточную таблицу
Запросы, которые доступны:
Post.findAll({ include: Tag })
Tag.findAll({ include: Post })
Запросы, которые не доступны:
Posts_tag.findAll({ include: Tag })
Posts_tag.findAll({ include: Post })

9.

Две связи один ко многим
// Model Post
static associate(models) {
this.hasMany(models.Posts_tag, { foreignKey: 'post_id' })
}
// Model Tag
static associate(models) {
this.hasMany(models.Posts_tag, { foreignKey: 'tag_id' })
}
// Model Posts_tag
static associate(models) {
this.belongsTo(models.Post, { foreignKey: 'post_id' })
this.belongsTo(models.Tag, { foreignKey: 'tag_id' })
}

10.

Две связи один ко многим
Запросы, которые доступны:
Posts_tag.findAll({ include: Post })
Posts_tag.findAll({ include: Tag })
Post.findAll({ include: Posts_tag })
Tag.findAll({ include: Posts_tag })
Запросы, которые не доступны:
Post.findAll({ include: Tag })
Tag.findAll({ include: Post })

11.

Комбинированный вариант
// Model Post
// Model Tag
static associate(models) {
static associate(models) {
this.belongsToMany(models.Tag, {
this.belongsToMany(models.Post, {
through: 'Posts_tag',
through: 'Posts_tag',
foreignKey: 'post_id',
foreignKey: 'tag_id',
});
});
this.hasMany(models.Posts_tag, {
this.hasMany(models.Posts_tag, {
foreignKey: 'post_id',
foreignKey: 'tag_id',
as: 'post',
as: 'tag',
});
}
});
}

12.

Комбинированный вариант
В модели Posts_tag указываем belongsTo как в предыдущем примере.
Если модель ссылается на одну и туже таблицу, как в предыдущем примере,
то необходимо использовать alias (as) в ассоциациях и методах sequelize.
Основное назначение алиасов - устранение неоднозначности при наличии
одноименных таблиц/полей.

13.

Комбинированный вариант
Примеры запроса с “as”:
Post.findAll({ include: { as: 'post', model: Posts_tag } });
Tag.findAll({ include: { as: 'tag', model: Posts_tag } });

14.

Вложенные include
Есть возможность совершать вложенные include.
На примере из предыдущего слайда можно сделать вложенные include:
Post.findAll({
include: {
as: 'post',
model: Posts_tag,
include: Tag
}
})

15.

Seeders

16.

Сиды
Сиды - это действие наполнения БД тестовыми данными.
В случае, если откатить миграции и снова накатить, то все данные будут
потеряны. Благодаря сидам можно в один клик снова наполнить БД и
заниматься разработкой, а не наполнением БД в очередной раз.

17.

Сиды
Чтобы создать сид, нужно воспользоваться командой sequelize-cli:
npx sequelize-cli seed:generate --name tag
После этой команды, в вашей папке seeders появится новый файл. Он будет
похож на файл миграции. В нем также будут функции up и down.

18.

Сиды
async up(queryInterface, Sequelize) {
async down(queryInterface, Sequelize) {
await queryInterface.bulkInsert(
'Tags',
null, {});
[
}
{ name: 'JavaScript' },
{ name: 'React' },
],
{},
);
}
await queryInterface.bulkDelete('Tags',

19.

Сиды
Для того, чтобы накатить сиды нужно воспользоваться командой:
npx sequelize-cli db:seed:all
Для того, чтобы откатить сиды нужно воспользоваться командой:
npx sequelize-cli db:seed:undo:all
Важно!
Порядок сидов также важен, как и в случае с миграциями. Сперва сидим
независимые данные (без внешних ключей), после зависимые.

20.

Сиды
Если несколько раз запустить команду сида, то сиды каждый раз будут дублировать
данные.
Чтобы этого избежать, можно задать сидам такое же поведение, как и у миграций
(будет проверка, был ли засижен файл). Это делается с помощью добавления в
database.json в свойство development следующих строк:
"seederStorage": "sequelize",
"seederStorageTableName": "SequelizeData"
English     Русский Правила