了解Sequelize数据库迁移和种子

时间:2017-12-14 17:43:17

标签: node.js database sequelize.js database-migration

我试图围绕Sequelize的迁移以及它们如何与种子(或者一般的迁移和种子)一起工作。 我设置了一切以使迁移工作。

首先,让我们创建一个users表:

// migrations/01-create-users.js
module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.createTable("Users", {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      email: {
        type: Sequelize.STRING
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE,
        defaultValue: Sequelize.literal('CURRENT_TIMESTAMP')
      },
      updatedAt: {
        type: Sequelize.DATE
      }
    });
  },
  down: (queryInterface, Sequelize) => {
    return queryInterface.dropTable("Users");
  }
};

精细。如果我想为一个(管理员)用户播种,我可以这样做:

// seeders/01-demo-user.js
module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.bulkInsert(
      "Users",
      [
        {
          email: "demo@demo.com"
        }
      ],
      {}
    );
  },

  down: (queryInterface, Sequelize) => {
    return queryInterface.bulkDelete("Users", null, {});
  }
};

然后为了让魔术发生,我做了:

$ sequelize db:migrate

在数据库中创建users表。在运行迁移之后,下一步是播种,所以:

$ sequelize db:seed:all

Tataa,现在我在users数据库中有一个用户。大。

但是现在我想将firstname添加到users表中,所以我必须添加另一个迁移:

// migrations/02-alter-users.js
module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.addColumn("Users", "firstname", {
      type: Sequelize.STRING
    });
  },
  down: (queryInterface, Sequelize) => {
    return queryInterface.removeColumn("Users", "firstname");
  }
};

再次运行迁移只会运行第二个迁移,因为它已保存在第一个已执行的数据库中。但默认情况下,sequelize重新运行所有播种机。那么我应该调整seeders/01-demo-user.js还是更改默认行为,并将播种机存储在数据库中并创建一个只更新firstname的新播客?

如果firstname无法null,然后首先运行迁移,然后旧版seeders/01-demo-user.js会抛出错误,因为firstname可以&#39 ; t null

重新播放播种机会导致另一个问题:已有一位用户使用demo@demo.com电子邮件。再次运行它将复制用户。或者我必须在播种机中检查这样的事情吗?

以前,我刚刚在迁移中添加了用户帐户,因此我可以确定它何时添加到数据库中以及何时必须更新它。但有人告诉我,我做错了,我必须使用播种机来完成这样的任务。

非常感谢任何帮助/见解。

3 个答案:

答案 0 :(得分:1)

以我的经验,迁移会改变结构。播种者...种子数据。最近,我在一个没有配置播种机的项目中。 https://sequelize.org/master/manual/migrations.html#seed-storage。这将允许您设置一个文件,以便您的数据不会多次播种。迁移配置也在那里。

答案 1 :(得分:1)

您好,请尝试使用批量更新...

'use strict';

module.exports = {
  up: (queryInterface, Sequelize) =>  queryInterface.addColumn(
        'Users',
        'user_type',
        {
          type: Sequelize.STRING,
          allowNull: false,
        }
      ).then(()=>
        queryInterface.bulkUpdate('Users', {
            user_type: 'simple_user',
        }, {
            is_deleted : 0,
        })
      ),

  down: (queryInterface, Sequelize) => 
    queryInterface.removeColumn('Users', 'user_type')
};

答案 2 :(得分:0)

在我看来,播种机只能运行一次,而迁移是您不断向数据库结构中逐层添加的一种。

我将使用播种器填充一些查找或其他很可能不会更改的数据或测试数据。在sequelize docs中,“种子文件是数据中的一些更改,可用于用示例数据或测试数据填充数据库表。”

如果要在数据结构已更改时进行一些动态数据更新,则可以根据需要直接在迁移中运行原始查询。因此,例如,如果您在up方法中添加了某些列,则可以根据您的业务逻辑来更新数据库中的行,例如:

// Add column, allow null at first
await queryInterface.addColumn("users", "user_type", {
    type: Sequelize.STRING,
    allowNull: true
});

// Update data
await queryInterface.sequelize.query("UPDATE users SET user_type = 'simple_user' WHERE is_deleted = 0;");

// Change column, disallow null
await queryInterface.changeColumn("users", "user_type", {
    type: Sequelize.STRING,
    allowNull: false
});

在Google网上论坛中,与此主题相关的还有一个有趣的discussion。希望对您有帮助。