【问题标题】:Create a table and add indexes in a single migration with Sequelize使用 Sequelize 在单个迁移中创建表并添加索引
【发布时间】:2017-07-31 03:50:05
【问题描述】:

在一次迁移中创建表并在其某些列上添加索引的正确方法是什么?

迁移示例:2012341234-create-todo.js

如何在“author_id”和“title”列上创建索引?

'use strict';
module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.createTable('Todos', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      author_id: {
        type: Sequelize.INTEGER,
        onDelete: 'CASCADE',
        references: {
          model: 'Authors',
          key: 'id',
          as: 'authorId'
        }
      },
      title: {
        type: Sequelize.STRING
      },

      content: {
        type: Sequelize.TEXT
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    });
  },
  down: (queryInterface, Sequelize) => {
    return queryInterface.dropTable('Todos');
  }
};

Sequelize 文档表明将像这样添加索引:

queryInterface.addIndex('Todos', ['author_id', 'title']);

这些方法可以链接吗? “上”和“下”只需要返回一个承诺吗?我在文档中没有看到任何关于它的内容。

【问题讨论】:

    标签: indexing migration sequelize.js


    【解决方案1】:

    我没有进行交易。我刚刚创建了表并一步添加了索引(唯一索引,这是我需要的):

        'use strict';
        const { DataTypes } = require('sequelize');
    
        module.exports = {
          up: async (queryInterface, Sequelize) => {
            return await queryInterface.createTable('exampleTable', {
              id: {
                type: DataTypes.INTEGER,
                primaryKey: true,
                autoIncrement: true
              },
              userId: {
                  type: DataTypes.INTEGER,
                  allowNull: false,
                  references: {
                      model: 'user',
                      key: 'id'
                  }
              },
              classId: {
                  type: DataTypes.INTEGER,
                  allowNull: false,
                  references: {
                      model: 'class',
                      key: 'id'
                  }
              },
          },
          {
              uniqueKeys: {
                unique_tag: {
                    customIndex: true,
                    fields: ["userId", "classId"]
                }
              }
            });
          },
    
          down: async (queryInterface, Sequelize) => {
            return await queryInterface.dropTable('exampleTable');
          }
        };
    

    【讨论】:

      【解决方案2】:

      如果第二步失败,则可接受的解决方案是有问题的。应该使用每个步骤中的事务来允许回滚,以确保在任何步骤遇到问题时撤消所有插入或更新的迁移步骤。例如:

      module.exports = {
       up: async (queryIntereface) => {
          const transaction = await queryInterface.sequelize.transaction();
      
          try {
            await queryInterface.createTable('Todos', {
              // columns...
            }, { transaction });
            await queryInterface.addIndex('Todos', ['author_id', 'title'], { transaction }));
      
      
            await transaction.commit();
          } catch (err) {
            await transaction.rollback();
            throw err;
          }
        },
      
        down: async (queryInterface) {
      
          etc...
      

      参考

      【讨论】:

        【解决方案3】:

        添加索引的最简单方法

        'use strict';
        
        module.exports = {
          up: (queryInterface, Sequelize) => {
            return queryInterface.addIndex('reports', ['client_id'])
              .then(() => {
                return queryInterface.addIndex('reports', ['report_name'])
              })
              .then(() => {
                return queryInterface.addIndex('reports', ['report_date'])
              })
          },
        
          down: (queryInterface, Sequelize) => {
            return queryInterface.removeIndex('reports', ['client_id'])
            .then(() => {
              return queryInterface.removeIndex('reports', ['report_name'])
            })
            .then(() => {
              return queryInterface.removeIndex('reports', ['report_date'])
            })
          }
        };
        

        【讨论】:

          【解决方案4】:

          我使用原始语法创建了一个全新的迁移文件

          module.exports = {
           up: (queryInterface) => {
           return queryInterface.sequelize.query('CREATE INDEX devices_mac_uuid ON 
            "Devices" ("mac","uuid")')
           },
           down: (queryInterface) => {
            return queryInterface.sequelize.query('DROP INDEX devices_mac_uuid')
           }
          }
          

          【讨论】:

          • 虽然您的建议会奏效,但它并不能回答“正确方法”的问题。如果您将每次迁移都限制在一个步骤中,您将失去上下文,并且每次构建应用程序时都会处理不必要数量的文件。事务的使用允许安全的多步骤迁移。有关示例,请参见交易答案。
          【解决方案5】:

          是的,这些方法可以链接。在您的情况下,您只需在 createTable 方法之后执行 addIndex

          return queryInterface.createTable('Todos', {
              // columns...
          }).then(() => queryInterface.addIndex('Todos', ['author_id', 'title']))
          .then(() => {
              // perform further operations if needed
          });
          

          【讨论】:

          • 如果 .addIndex 失败,则 .createTable 将保留。这不是如何进行具有多个步骤的迁移。查看使用事务的答案。
          猜你喜欢
          • 1970-01-01
          • 2019-04-16
          • 2016-05-28
          • 2018-11-18
          • 2018-01-31
          • 2014-02-07
          • 2015-07-04
          • 1970-01-01
          • 2020-08-25
          相关资源
          最近更新 更多