如何进行knex.js迁移?

Eri*_*ell 21 javascript knex.js

我还不确定如何使用knex进行迁移.这是我到目前为止所拥有的.它可以工作up,但down即使foreign_key_checks = 0,也会给我FK约束错误.

exports.up = function(knex, Promise) {
  return Promise.all([
    knex.raw('SET foreign_key_checks = 0;'),

    /* CREATE Member table */
    knex.schema.createTable('Member', function (table) {
      table.bigIncrements('id').primary().unsigned();
      table.string('email',50);
      table.string('password');

      /* CREATE FKS */
      table.bigInteger('ReferralId').unsigned().index();
      table.bigInteger('AddressId').unsigned().index().inTable('Address').references('id');
    }),

    /* CREATE Address table */
    knex.schema.createTable('Address', function (table) {
      table.bigIncrements('id').primary().unsigned();
      table.index(['city','state','zip']);

      table.string('city',50).notNullable();
      table.string('state',2).notNullable();
      table.integer('zip',5).unsigned().notNullable();
    }),

    knex.raw('SET foreign_key_checks = 1;')
  ]);
};

exports.down = function(knex, Promise) {
  return Promise.all([
    knex.raw('SET foreign_key_checks = 0;'),

    knex.schema.dropTable('Address'),

    knex.schema.dropTable('Member'),

    knex.raw('SET foreign_key_checks = 1;')

  ]);
};
Run Code Online (Sandbox Code Playgroud)

nzh*_*nry 14

jedd.ahyoung是对的.您不需要将连接池限制为1.您只需链接您的承诺,以便它们不会并行运行.

例如:

exports.up = function(knex, Promise) {
  return removeForeignKeyChecks()
    .then(createMemberTable)
    .then(createAddressTable)
    .then(addForeignKeyChecks);

  function removeForeignKeyChecks() {
    return knex.raw('SET foreign_key_checks = 0;');
  }

  function addForeignKeyChecks() {
    return knex.raw('SET foreign_key_checks = 1;');
  }

  function createMemberTable() {
    return knex.schema.createTable('Member', function (table) {
      table.bigIncrements('id').primary().unsigned();
      table.string('email',50);
      table.string('password');

      /* CREATE FKS */
      table.bigInteger('ReferralId').unsigned().index();
      table.bigInteger('AddressId').unsigned().index().inTable('Address').references('id');
    });
  }

  function createAddressTable() {
    return knex.schema.createTable('Address', function (table) {
      table.bigIncrements('id').primary().unsigned();
      table.index(['city','state','zip']);

      table.string('city',50).notNullable();
      table.string('state',2).notNullable();
      table.integer('zip',5).unsigned().notNullable();
    });
  }
};
Run Code Online (Sandbox Code Playgroud)

此外,我可能会遗漏一些内容,但如果您在成员表之前创建地址表,则看起来您不需要删除然后恢复外键检查.

以下是最终代码的外观:

exports.up = function(knex, Promise) {
  return createAddressTable()
    .then(createMemberTable);

  function createMemberTable() {
    return knex.schema.createTable('Member', function (table) {
      table.bigIncrements('id').primary().unsigned();
      table.string('email',50);
      table.string('password');

      /* CREATE FKS */
      table.bigInteger('ReferralId').unsigned().index();
      table.bigInteger('AddressId').unsigned().index().inTable('Address').references('id');
    });
  }

  function createAddressTable() {
    return knex.schema.createTable('Address', function (table) {
      table.bigIncrements('id').primary().unsigned();
      table.index(['city','state','zip']);

      table.string('city',50).notNullable();
      table.string('state',2).notNullable();
      table.integer('zip',5).unsigned().notNullable();
    });
  }
};
Run Code Online (Sandbox Code Playgroud)


Eri*_*ell 9

因为连接池而弄清楚它无法正常工作.它将使用不同的连接来运行每个迁移任务,这会导致无法正确设置外键检查.设置

pool:{
  max:1
}
Run Code Online (Sandbox Code Playgroud)

在迁移配置文件中修复此问题.

  • 似乎真正的问题是函数可以并行运行.与下面的交易答案类似,您可能需要以特定方式链接您的承诺以获得您想要的. (10认同)

小智 5

我通过交易解决了这个问题

transation.js

module.exports = function transaction(fn) {
    return function _transaction(knex, Promise) {
        return knex.transaction(function(trx) {
            return trx
                .raw('SET foreign_key_checks = 0;')
                .then(function() {
                    return fn(trx, Promise);
                })
                .finally(function() {
                    return trx.raw('SET foreign_key_checks = 1;');
                });
        });
    };
}
Run Code Online (Sandbox Code Playgroud)

迁移档案

var transaction = require('../transaction');

function up(trx, Promise) {
    return trx.schema
       .createTable('contract', function(table) {
           table.boolean('active').notNullable();                                              
           table.integer('defaultPriority').unsigned().references('priority.id');                             
           table.integer('defaultIssueStatus').unsigned().references('issueStatus.id');
           table.integer('owner').notNullable().unsigned().references('user.id'); 
       })

       .createTable('user', function (table) {
           table.increments('id').primary();
           table.datetime('createdAt');
           table.datetime('updatedAt');

           table.string('phoneNumber').notNullable().unique();
           table.string('password').notNullable();            
           table.string('name').notNullable().unique();       
           table.string('email');                             
           table.string('status');                            
           table.string('roles').defaultTo('user');           
           table.integer('contract').unsigned().references('contract.id');
       });
}

function down(trx, Promise) {
    return trx.schema
        .dropTable('contract')
        .dropTable('user');
}

exports.up = transaction(up);
exports.down = transaction(down);
Run Code Online (Sandbox Code Playgroud)