在迁移期间不会创建引用外键的Knex.js列

时间:2018-06-19 03:19:17

标签: javascript knex.js

当我执行knex.js迁移时,除了下面'recipe-in​​gredient'连接表中的两个外键表外,所有内容都会构建。有谁看到我做错了什么?这是迁移中的第三个表:

exports.up = function(knex, Promise) {
    return Promise.all([
        knex.schema.hasTable('recipe').then((exists) => {
            console.log('does knex have recipe table?', exists);
            if (!exists) {
                return knex.schema.createTable('recipe', (table) => {
                    table.uuid('id');
                    table.string('name');
                    table.string('description');
                })
            }
        }),
        knex.schema.hasTable('ingredient').then((exists) => {
            console.log('does knex have ingredient table?', exists);
            if (!exists) {
                return knex.schema.createTable('ingredient', (table) => {
                    table.uuid('id');
                    table.string('name');
                })
            }
        }),
        knex.schema.hasTable(`recipe-ingredient`).then((exists) => {
            console.log('does knex have recipe-ingredient table?', exists);
            if (!exists) {
                return knex.schema.createTable(`recipe-ingredient`, (table)=> {
                    table.uuid('recipe_id').references('id').inTable('recipe').notNull();
                    table.uuid('ingredient_id').references('id').inTable('ingredient').notNull();
                    table.string('qty');  // <-- chose string instead of int because receipes include qty such as '1/3 cup', '1 teaspoon', etc.
                })
            }
        })
    ])
};

exports.down = function(knex, Promise) {
    return Promise.all([
        knex.schema.dropTable('recipe-ingredient'),
        knex.schema.dropTable('ingredient'),
        knex.schema.dropTable('recipe')
    ])
};

这是我的knexfile.js:

require('dotenv').config();

module.exports = {

  development: {
    client: 'mysql',
    connection: {
      host: process.env.DATABASE_HOST_DEV || '127.0.0.1',
      user: process.env.DATABASE_USER_DEV,
      password: process.env.DATABASE_PASSWORD_DEV,
      database: process.env.DATABASE_NAME_DEV
    },
    migrations: {
      directory: __dirname+'/database/migrations'
    }
  },

  staging: {
    client: 'mysql',
    connection: {
      host: '127.0.0.1',
      user: 'root',
      password: 'password',
      database: 'recipes'
    },
    pool: {
      min: 2,
      max: 10
    },
    migrations: {
      directory: __dirname+'/database/migrations'
    }
  },

  production: {
    client: 'mysql',
    connection: {
      host: process.env.DATABASE_HOST,
      user: process.env.DATABASE_USER,
      password: process.env.DATABASE_PASSWORD,
      database: process.env.DATABASE_NAME
    },
    pool: {
      min: 2,
      max: 10
    },
    migrations: {
      directory: __dirname+'/database/migrations'
    }
  }

};

请注意,.env文件中的变量没什么特别之处。只是基本的用户名,密码和数据库名称。

1 个答案:

答案 0 :(得分:1)

您不应使用promise.all并并行运行所有查询。

IIRC knex为这些查询创建事务,但是实际上mysql在第一个CREATE TABLE语句之后执行隐式提交,因此事务将被提交,其余表创建可能以多种方式失败。

Knex可能会说它无法对已提交的事务执行更多查询,或者可能会忽略其他查询,或者无论如何都可以在事务外部(但通过相同的数据库连接)运行这些查询。很难说运行该迁移时会发生什么,但是绝对不能完全满足您的期望。

这应该更好地工作:

exports.up = function(knex, Promise) {
    return knex.schema.hasTable('recipe').then((exists) => {
        console.log('does knex have recipe table?', exists);
        if (!exists) {
            return knex.schema.createTable('recipe', (table) => {
                table.uuid('id');
                table.string('name');
                table.string('description');
            });
        }
    }).then(() => {
        return knex.schema.hasTable('ingredient').then((exists) => {
            console.log('does knex have ingredient table?', exists);
            if (!exists) {
                return knex.schema.createTable('ingredient', (table) => {
                    table.uuid('id');
                    table.string('name');
                })
            }
        });
    }).then(() => {
        return knex.schema.hasTable(`recipe-ingredient`).then((exists) => {
            console.log('does knex have recipe-ingredient table?', exists);
            if (!exists) {
                return knex.schema.createTable(`recipe-ingredient`, (table)=> {
                    table.uuid('recipe_id').references('id').inTable('recipe').notNull();
                    table.uuid('ingredient_id').references('id').inTable('ingredient').notNull();
                    table.string('qty');  // <-- chose string instead of int because receipes include qty such as '1/3 cup', '1 teaspoon', etc.
                })
            }
        })
    });
};

exports.down = function(knex, Promise) {
    return knex.schema.dropTable('recipe-ingredient')
      .then(() => knex.schema.dropTable('ingredient'))
      .then(() => knex.schema.dropTable('recipe'));
};