Sequelize: семя с ассоциациями

У меня есть 2 модели, Курсы и Видео, например. И на курсах есть много видео.

// course.js
'use strict';

module.exports = (sequelize, DataTypes) => {
  const Course = sequelize.define('Course', {
    title: DataTypes.STRING,
    description: DataTypes.STRING
  });

  Course.associate = models => {
    Course.hasMany(models.Video);
  };

  return Course;
};


// video.js
'use strict';

module.exports = (sequelize, DataTypes) => {
  const Video = sequelize.define('Video', {
    title: DataTypes.STRING,
    description: DataTypes.STRING,
    videoId: DataTypes.STRING
  });

  Video.associate = models => {
    Video.belongsTo(models.Course, {
      onDelete: "CASCADE",
      foreignKey: {
        allowNull: false
      }
    })
  };

  return Video;
};

Я хочу создать семена с курсами, которые включают видео. Как я могу это сделать? Я не знаю, как создавать сиды с включенными видео.


person zett    schedule 11.02.2018    source источник


Ответы (3)


Вы можете использовать queryInterface Sequelize, чтобы перейти к необработанному SQL, чтобы вставить экземпляры модели, требующие ассоциаций. В вашем случае проще всего создать один сидер для курсов и видео. (Одно примечание: я не знаю, как вы определяете свой первичный и внешний ключ, поэтому я делаю предположение, что в таблице видео есть поле course_id.)

module.exports = {
  up: async (queryInterface) => {
    await queryInterface.bulkInsert('courses', [
      {title: 'Course 1', description: 'description 1', id: 1}
      {title: 'Course 2', description: 'description 2', id: 2}
    ], {});

    const courses = await queryInterface.sequelize.query(
      `SELECT id from COURSES;`
    );

    const courseRows = courses[0];

    return await queryInterface.bulkInsert('videos', [
      {title: 'Movie 1', description: '...', id: '1', course_id: courseRows[0].id}
      {title: 'Movie 2', description: '...', id: '2', course_id: courseRows[0].id},
      {title: 'Movie 3', description: '...', id: '3', course_id: courseRows[0].id},
    ], {});
  },

  down: async (queryInterface) => {
    await queryInterface.bulkDelete('videos', null, {});
    await queryInterface.bulkDelete('courses', null, {});
  }
};
person mcranston18    schedule 12.02.2018
comment
в разделе down, не должны ли мы удалить столбец видео перед столбцом курсов из-за ограничения внешнего ключа. Извините, однако, за придирчивость. - person sameer manek; 03.09.2018
comment
пожалуйста, проверьте stackoverflow. ком/вопросы/52227663/ - person sameer manek; 07.09.2018
comment
Последняя версия выдаст «ожидание допустимо только в асинхронной функции». - person Jeffery ThaGintoki; 23.09.2019

При передаче { returning: true } в поле параметров bulkInsert возвращаются созданные объекты.

    let createdOjects = await queryInterface.bulkInsert("table_name", data_to_be_inserted, { returning: true });

Кроме того, вы можете передать массив с интересующими вас полями, например. идентификатор { returning: ['id'] }, и это вернет массив идентификаторов созданных объектов

    let createdIds = await queryInterface.bulkInsert("table_name", data_to_be_inserted, { returning: ['id'] });

Вы можете просмотреть возвращенные объекты/идентификаторы и вставить вложенные объекты, используя bulkInsert.

Образец кода:

module.exports = {
  up: async (queryInterface) => {
    let courses = ["..."]
    let videos = ["..."]
    let videoIds = await queryInterface.bulkInsert("courses", courses, { returning: ["id"] });
    
    //add courseId to each video object -- depends on your scheme

     await queryInterface.bulkInsert("videos", videos);
  },

  down: async (queryInterface) => {
    await queryInterface.bulkDelete("videos", null, {});
    await queryInterface.bulkDelete("courses", null, {});
  },
};
person Ahmed Elazazy    schedule 22.09.2020

Метод bulkInsert возвращает обещание, которое разрешено с идентификатором первого вставленного элемента. Мы можем использовать эту информацию для вставки видео. Это может выглядеть так:

function getId( firstId, items, needly ) {
    for ( let i = 0; i < items.length; i++ ) {
        if ( items[i].title === needly ) {
            return firstId + i;
        }
    }

    return null;
}

exports.up = async ( queryInterface, Sequelize ) => {
    const courses = [
        {
            title: 'Course 1',
            description: '...',
        },
        {
            title: 'Course 2',
            description: '...',
        },
        {
            title: 'Course 3',
            description: '...',
        },
        {
            title: 'Course 4',
            description: '...',
        },
        {
            title: 'Course 5',
            description: '...',
        },
    ];

    const firstId = await queryInterface.bulkInsert( 'courses', courses, {} );
    const course2Id = getId( firstId, courses, 'Course 2' );
    const course5Id = getId( firstId, courses, 'Course 5' );

    return queryInterface.bulkInsert( 'categories', [
        { title: 'Video 1', description: '...', courseId: course2Id },
        { title: 'Video 2', description: '...', courseId: course2Id },
        { title: 'Video 3', description: '...', courseId: course5Id },
        { title: 'Video 4', description: '...', courseId: course5Id },
        { title: 'Video 5', description: '...', courseId: course5Id },
    ], {} );
};

exports.down = async ( queryInterface ) => {
    await queryInterface.bulkDelete( 'videos', null, {} );
    await queryInterface.bulkDelete( 'courses', null, {} );
}
person Eugene Manuilov    schedule 25.11.2019
comment
Следует упомянуть, что этот метод будет работать только с увеличивающимися целочисленными идентификаторами, но полезно знать, что bulkInsert будет разрешаться в первый вставленный идентификатор. - person Hunter Mueller; 16.04.2020