在 Knex 迁移中创建数据库

Ben*_*dai 8 sql migration postgresql knex.js

我认为从第一个数据库交互开始使用迁移是个好主意,所以我想为数据库创建创建迁移。

knexfile.js

'use strict';

require('dotenv').config({ path: 'process.env' });

const config =  {
  client: 'pg',
  connection: {
    host: process.env.DB_URL,
  },
};


module.exports = config;
Run Code Online (Sandbox Code Playgroud)

迁移文件:

'use strict';

exports.up = function(knex, Promise) {
  return knex.raw('CREATE DATABASE asd');
};

exports.down = function(knex, Promise) {
  return knex.raw('DROP DATABASE asd');
};

exports.config = {
  transaction: false
};
Run Code Online (Sandbox Code Playgroud)

到目前为止它工作正常,但是当我添加database到 knexfile 配置时,它无法迁移,因为 Knex 尝试连接到不存在的数据库。

我还尝试为这个单一的迁移使用一个新的 Knex 实例,例如:

exports.up = function(_, Promise) {
  // Remove database from config so Knex won't try to connect
  // to a non existing database.
  const config = require(process.cwd() + '/knexfile');
  config.connection.database = null;
  const knex = require('knex')(config);

  return knex.raw('CREATE DATABASE asd');
};
Run Code Online (Sandbox Code Playgroud)

但是 knex 在迁移之前已经初始化,因此它失败并出现相同的错误:

error: database "asd" does not exist
Run Code Online (Sandbox Code Playgroud)

关于如何从 Knex 迁移创建数据库的任何想法?我对任何关于数据库创建的最佳实践持开放态度,它可以处理不同环境的 db url。

Ben*_*dai 9

我添加了一个postinstall脚本来运行这样的脚本:

'use strict';

async function createDatabase() {
  const config = require(process.cwd() + '/knexfile');
  config.connection.database = null;
  const knex = require('knex')(config);

  await knex.raw('CREATE DATABASE asd');
  await knex.destroy();
}

createDatabase();
Run Code Online (Sandbox Code Playgroud)

这样我就没有将此步骤存储为迁移,但我真的没有看到一个想要删除整个数据库的用例。

您如何看待这种方法?


ben*_*sha 8

由于事先不知道数据库,因此最简单的方法是使用迁移 API 创建您自己的脚本。应该可以动态指定您的数据库名称

另存为migrate.js

const Knex = require('knex')

// You can dynamically pass the database name
// as a command-line argument, or obtain it from
// a .env file
const databaseName = 'database_name'

const connection = {
  host: 'localhost',
  user: 'root',
  password: 'password'
}

async function main() {
  let knex = Knex({
    client: 'mysql',
    connection
  })
  
  // Lets create our database if it does not exist
  await knex.raw('CREATE DATABASE IF NOT EXISTS ??', databaseName)
  

  // Now that our database is known, let's create another knex object
  // with database name specified so that we can run our migrations
  knex = Knex({
    client: 'mysql',
    connection: {
      ...connection,
      database: databaseName,
    }
  })

  // Now we can happily run our migrations
  await knex.migrate.latest()

  // Done!!
}

main().catch(console.log).then(process.exit)
Run Code Online (Sandbox Code Playgroud)

您现在可以运行您的脚本

node migrate.js
Run Code Online (Sandbox Code Playgroud)

您可以使用.env文件来存储配置或将它们作为命令行参数传递


Mik*_*stö 6

Knex 并不真正支持轻松创建数据库。

首先运行迁移必须创建表,其中包含已运行的迁移信息,因此数据库必须在执行迁移之前存在。

通常你希望有不同的配置文件来创建数据库,用户有足够的权限来创建数据库并连接到例如名为postgresor 的数据库template1

像那样,您应该能够通过创建简单的脚本来完成,这确保在运行迁移之前创建数据库。

还有一个工具knex-db-manager(主要由我编写)可能有助于创建数据库所有者用户/数据库的任务。