Knex可以在Node.JS和浏览器中用作SQL查询生成器,但限于WebSQL的约束(例如无法删除表或读取模式)。不建议在浏览器中编写SQL查询以在服务器上执行,因为这可能会导致严重的安全漏洞。在WebSQL外部构建的浏览器主要是出于学习目的-例如,您可以弹出控制台并使用knex对象在此页面上构建查询。

Node.js

Knex的主要目标环境是Node.js,您需要安装该knex库,然后安装适当的数据库库:pgPostgreSQL和Amazon Redshift,mysqlMySQL或MariaDB,sqlite3SQLite3或mssqlMSSQL。

  1. $ npm install knex --save
  2. # Then add one of the following (adding a --save) flag:
  3. $ npm install pg
  4. $ npm install sqlite3
  5. $ npm install mysql
  6. $ npm install mysql2
  7. $ npm install oracledb
  8. $ npm install mssql

如果要使用MariaDB实例,则可以使用mysql驱动程序。

浏览器

Knex可以使用JavaScript构建工具,例如内置browserify的WebPack。实际上,本文档使用包含knex的webpack构建。在此页面上查看源代码以查看浏览器的实际运行情况(全局knex变量)。

初始化库

knex模块本身就是一个函数,它接受Knex的配置对象,并接受一些参数。该client参数是必需的,并确定将哪个客户端适配器与库一起使用。

var knex = require('knex')({
  client: 'mysql',
  connection: {
    host : '127.0.0.1',
    user : 'your_database_user',
    password : 'your_database_password',
    database : 'myapp_test'
  }
});

连接选项直接传递到适当的数据库客户端以创建连接,并且可以是对象,连接字符串或返回对象的函数:
注意:Knex的PostgreSQL客户端允许您使用附加选项“ searchPath”自动为每个连接设置初始搜索路径,如下所示。

var pg = require('knex')({
  client: 'pg',
  connection: process.env.PG_CONNECTION_STRING,
  searchPath: ['knex', 'public'],
});

注意:使用SQLite3适配器时,需要文件名而不是网络连接。例如:

var knex = require('knex')({
  client: 'sqlite3',
  connection: {
    filename: "./mydb.sqlite"
  }
});

注意:当您使用PostgreSQL适配器连接非标准数据库时,可以在knex配置中添加数据库版本。

var knex = require('knex')({
  client: 'pg',
  version: '7.2',
  connection: {
    host : '127.0.0.1',
    user : 'your_database_user',
    password : 'your_database_password',
    database : 'myapp_test'
  }
});
var knex = require('knex')({
  client: 'mysql',
  version: '5.7',
  connection: {
    host : '127.0.0.1',
    user : 'your_database_user',
    password : 'your_database_password',
    database : 'myapp_test'
  }
});

可以使用一个函数动态确定连接配置。此函数不接收任何参数,并返回配置对象或对配置对象的承诺。

var knex = require('knex')({
  client: 'sqlite3',
  connection: () => ({
    filename: process.env.SQLITE_FILENAME
  })
});

默认情况下,将缓存通过函数接收的配置对象,并将其重新用于所有连接。若要更改此行为,expirationChecker可以将函数作为配置对象的一部分返回。在expirationChecker尝试创建新的连接前,征求意见,并在情况下,它会返回true,新的配置对象被检索。例如,要使用寿命有限的身份验证令牌:

var knex = require('knex')({
  client: 'postgres',
  connection: async () => {
    const { token, tokenExpiration } = await someCallToGetTheToken();
    return {
      host : 'your_host',
      user : 'your_database_user',
      password : token,
      database : 'myapp_test',
      expirationChecker: () => {
        return tokenExpiration <= Date.now();
      }
    };
  }
});

您也可以通过unix域套接字连接,该套接字将忽略主机和端口。

var knex = require('knex')({
  client: 'mysql',
  connection: {
    socketPath : '/path/to/socket.sock',
    user : 'your_database_user',
    password : 'your_database_password',
    database : 'myapp_test'
  }
});

userParams是一个可选参数,允许您传递可通过knex.userParams属性访问的任意参数:

var knex = require('knex')({
  client: 'mysql',
  connection: {
    host : '127.0.0.1',
    user : 'your_database_user',
    password : 'your_database_password',
    database : 'myapp_test'
  },
  userParams: {
    userParam1: '451'
  }
});

初始化库通常只应在应用程序中发生一次,因为它会为当前数据库创建一个连接池,因此应在整个库中使用从initialize调用返回的实例。
为您感兴趣的特定SQL类型指定客户端。

var pg = require('knex')({client: 'pg'});
knex('table').insert({a: 'b'}).returning('*').toString();
// "insert into "table" ("a") values ('b')"
pg('table').insert({a: 'b'}).returning('*').toString();
// "insert into "table" ("a") values ('b') returning *"

获取参数化实例

withUserParams如果要获取具有自定义参数的副本(具有相同的连接),可以在Knex实例上调用method (例如,执行具有不同参数的相同迁移)

var knex = require('knex')({
  // Params
});
var knexWithParams = knex.withUserParams({customUserParam: 'table1'});
var customUserParam = knexWithParams.userParams.customUserParam;

调试

debug: true在初始化对象上传递标志将打开所有查询的调试功能。

asyncStackTraces

asyncStackTraces: true在初始化对象上传递标志将打开所有查询构建器,原始查询和模式构建器的堆栈跟踪捕获。当数据库驱动程序返回错误时,将捕获此先前捕获的堆栈跟踪,而不是新的堆栈跟踪。这有助于减轻awaitnode.js / V8中的默认行为,这会破坏堆栈。这具有较小的性能开销,因此建议仅用于开发。默认关闭。

Pooling

由配置创建的客户端使用tarn.js库初始化连接池。该连接池min: 2, max: 10的MySQL和PG库的默认设置为a ,而sqlite3的连接为单个连接(由于在单个文件上使用多个连接的问题)。要更改池的配置设置,请将一个pool选项作为初始化块中的键之一传递。
查看tarn.js库以获取更多信息。

var knex = require('knex')({
  client: 'mysql',
  connection: {
    host : '127.0.0.1',
    user : 'your_database_user',
    password : 'your_database_password',
    database : 'myapp_test'
  },
  pool: { min: 0, max: 7 }
});

如果您需要显式拆除连接池,则可以使用knex.destroy([callback])。您可以knex.destroy通过传递回调或将链作为承诺来使用,但不能同时使用。要手动初始化销毁的连接池,可以使用knex.initialize([config]),如果未传递任何配置,它将使用所使用的第一个knex配置。

afterCreate

afterCreate当池从数据库服务器获取新连接时,将调用回调(rawDriverConnection,已完成)。必须调用done(err,connection)回调,knex以便能够确定连接是否正常,或者是否应立即从池中将其丢弃。

var knex = require('knex')({
  client: 'pg',
  connection: {...},
  pool: {
    afterCreate: function (conn, done) {
      // in this example we use pg driver's connection API
      conn.query('SET timezone="UTC";', function (err) {
        if (err) {
          // first query failed, return error and don't try to make next query
          done(err, conn);
        } else {
          // do the second query...
          conn.query('SELECT set_limit(0.01);', function (err) {
            // if err is not falsy, connection is discarded from pool
            // if connection aquire was triggered by a query the error is passed to query promise
            done(err, conn);
          });
        }
      });
    }
  }
});

acquisitionConnectionTimeout

acquireConnectionTimeout默认值为60000ms,用于确定在无法获取连接时,knex在引发超时错误之前应等待多长时间。造成这种情况的最常见原因是耗尽了所有池的事务连接,然后在池仍然满的情况下尝试在事务外部运行查询。引发的错误将提供有关连接所针对的查询的信息,以简化查找罪魁祸首的工作。

var knex = require('knex')({
  client: 'pg',
  connection: {...},
  pool: {...},
  acquireConnectionTimeout: 10000
});

fetchAsString

由Oracledb使用。类型数组。有效类型为“ DATE”,“ NUMBER”和“ CLOB”。当查询具有指定类型之一的任何列时,列数据将作为字符串而不是默认表示形式返回。

var knex = require('knex')({
  client: 'oracledb',
  connection: {...},
  fetchAsString: [ 'number', 'clob' ]
});

Migrations

为了方便起见,可以在初始化库时指定任何迁移配置。阅读“ 迁移”部分以了解更多信息和配置选项的完整列表。

var knex = require('knex')({
  client: 'mysql',
  connection: {
    host : '127.0.0.1',
    user : 'your_database_user',
    password : 'your_database_password',
    database : 'myapp_test'
  },
  migrations: {
    tableName: 'migrations'
  }
});

postProcessResponse

在将返回的行传递给用户之前,需要修改返回的行。例如,可以使用此钩子对返回的列进行snake_case-> camelCase转换。该queryContext如果配置为通过查询生成器实例只能queryContext

var knex = require('knex')({
  client: 'mysql',
  // overly simplified snake_case -> camelCase converter
  postProcessResponse: (result, queryContext) => {
    // TODO: add special case for raw results (depends on dialect)
    if (Array.isArray(result)) {
      return result.map(row => convertToCamel(row));
    } else {
      return convertToCamel(result);
    }
  }
});

wrapIdentifier

Knex支持将标识符名称自动转换为每种方言的引用版本。例如'Table.columnName as foo'对于PostgreSQL转换为“ Table”。“ columnName”作为“ foo”。
有了wrapIdentifier一个可以覆盖标识符是如何改变的方式。它可以用于覆盖默认功能,例如帮助执行camelCase-> snake_case转换。
转换功能wrapIdentifier(value, dialectImpl, context): string将标识符的每个部分作为一个单独的value,来自方言实现和的原始转换功能queryContext,仅当通过builder.queryContext为查询构建器实例配置,并通过schema.queryContext为模式构建器实例配置时,此功能才可用.queryContext。例如,查询生成器,knex('table').withSchema('foo').select('table.field as otherName').where('id', 1)将调用wrapIdentifier转换为以下值'table''foo''table''field''otherName''id'

var knex = require('knex')({
  client: 'mysql',
  // overly simplified camelCase -> snake_case converter
  wrapIdentifier: (value, origImpl, queryContext) => origImpl(convertToSnakeCase(value))
});

日志

Knex包含一些内部日志功能,用于在适用时打印警告,错误,弃用和调试信息。这些日志功能通常记录到控制台,但可以使用log选项覆盖并提供替代功能。不同的日志功能可用于单独的knex实例。

var knex = require('knex')({
   log: {
    warn(message) {
    },
    error(message) {
    },
    deprecate(message) {
    },
    debug(message) {
    },
  }
});

TypeScript支持

虽然knex是用JavaScript编写的,但官方支持的TypeScript绑定可用(在knex npm包中)。
但是,应注意,TypeScript支持目前是尽力而为的。Knex具有非常灵活的API,并非所有使用模式都可以进行类型检查,在大多数情况下,我们会在灵活性方面犯错。特别是,缺少类型错误目前不能保证所生成的查询将是正确的,因此即使您使用的是TypeScript,也建议为它们编写测试。
许多API接受TRecordTResult键入参数,通过它们我们可以分别指定数据库表中行的类型和查询结果的类型。当使用支持TypeScript的编辑器(例如VSCode)时,这有助于自动完成。