在Knex迁移中创建数据库。

11
我认为从第一次与数据库交互开始使用迁移是个好主意,因此我希望为数据库创建一个迁移。
knexfile.js
'use strict';

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

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


module.exports = config;

迁移文件:

'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
};

到这个点为止它可以正常工作,但是当我在knexfile配置中添加database时,它无法进行迁移,因为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');
};

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

error: database "asd" does not exist

你有没有关于如何从Knex迁移创建数据库的想法?我希望能了解一些最佳实践,以便可以处理不同环境下的数据库URL。

3个回答

10

我已经添加了一个 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();

这样我就没有将这一步存储为迁移,但是我真的看不到有什么用例需要删除整个数据库。

你对这种方法有什么想法?


常见的用例是使用临时数据库来运行集成测试。 - davidmwhynot
如果你设置 database = null,那么它会尝试针对与用户同名的数据库运行。至少在postgres中是这样工作的。对于postgres,我认为在创建/删除其他数据库时应该使用 postgres 数据库。 - icc97

9

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

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

通常您会希望为创建数据库使用不同的配置文件,其中包含具有足够权限创建数据库并连接到名为postgrestemplate1的数据库的用户。

通过创建简单的脚本,您应该能够做到这一点,以确保在运行迁移之前已创建DB。

此外,有一个名为knex-db-manager的工具(由我主要编写),可以帮助创建数据库所有者用户/数据库的任务。


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)

您现在可以运行您的脚本。
node migrate.js

你可以使用一个.env文件来存储你的配置,或者将它们作为命令行参数传递。

所以,当您第一次不指定数据库名称时,它会连接到默认的PostgreSQL数据库或与您的用户同名的数据库,对吗? 然后,您可以创建另一个数据库并连接到它。简而言之,您永远不能只连接到服务器,您必须连接到该服务器中的一个数据库,如果错误请纠正。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接