【问题标题】:Sequelize: seed with associationsSequelize:带有关联的种子
【发布时间】:2018-07-21 18:45:45
【问题描述】:

例如,我有 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;
};

我想用包含视频的课程创建种子。我怎样才能做到?我不知道如何使用包含的视频创建种子。

【问题讨论】:

    标签: javascript node.js sequelize.js models seeding


    【解决方案1】:

    您可以使用 Sequelize 的 queryInterface 下拉到原始 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, {});
      }
    };
    

    【讨论】:

    • down 部分中,由于外键约束,我们不应该删除课程列之前的视频列。抱歉,我很挑剔。
    • 最新版本会抛出'await is only valid in async function'
    【解决方案2】:

    bulkInsert 的选项字段中传递{ returning: true } 时,它将返回创建的对象。

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

    此外,您可以传递一个包含您感兴趣的字段的数组,例如ID { returning: ['id'] },这将返回创建对象的 ID 数组

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

    您也可以使用bulkInsert 循环遍历返回的对象/ID 并插入嵌套对象。

    示例代码:

    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, {});
      },
    };
    

    【讨论】:

    【解决方案3】:

    bulkInsert 方法返回一个用第一个插入项的 ID 解析的承诺。我们可以使用这些信息来插入视频。它可能看起来像这样:

    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, {} );
    }
    

    【讨论】:

    • 应该提到这种技术只适用于递增的整数 ID,但很高兴知道 bulkInsert 将解析为第一个插入的 ID。
    猜你喜欢
    • 2014-11-07
    • 1970-01-01
    • 1970-01-01
    • 2017-06-10
    • 2019-02-03
    • 2016-11-20
    • 2019-02-13
    • 2016-04-11
    • 2021-03-16
    相关资源
    最近更新 更多