扩展数据类型
您试图实现的类型很可能已包含在 DataTypes 中。如果新的数据类型没有包含,本手册将展示如何自己编写它。
Sequelize 不会在数据库中创建新的数据类型。本教程解释如何使 Sequelize 识别新的数据类型,并假设这些新的数据类型已在数据库中创建。
要扩展 Sequelize 数据类型,请在创建任何 Sequelize 实例之前进行操作。
示例
在本示例中,我们将创建一个名为 SOMETYPE
的类型,它复制了内置数据类型 DataTypes.INTEGER(11).ZEROFILL.UNSIGNED
。
const { Sequelize, DataTypes, Utils } = require('Sequelize');
createTheNewDataType();
const sequelize = new Sequelize('sqlite::memory:');
function createTheNewDataType() {
class SOMETYPE extends DataTypes.ABSTRACT {
// Mandatory: complete definition of the new type in the database
toSql() {
return 'INTEGER(11) UNSIGNED ZEROFILL';
}
// Optional: validator function
validate(value, options) {
return typeof value === 'number' && !Number.isNaN(value);
}
// Optional: sanitizer
_sanitize(value) {
// Force all numbers to be positive
return value < 0 ? 0 : Math.round(value);
}
// Optional: value stringifier before sending to database
_stringify(value) {
return value.toString();
}
// Optional: parser for values received from the database
static parse(value) {
return Number.parseInt(value);
}
}
// Mandatory: set the type key
SOMETYPE.prototype.key = SOMETYPE.key = 'SOMETYPE';
// Mandatory: add the new type to DataTypes. Optionally wrap it on `Utils.classToInvokable` to
// be able to use this datatype directly without having to call `new` on it.
DataTypes.SOMETYPE = Utils.classToInvokable(SOMETYPE);
// Optional: disable escaping after stringifier. Do this at your own risk, since this opens opportunity for SQL injections.
// DataTypes.SOMETYPE.escape = false;
}
创建此新数据类型后,您需要在每个数据库方言中映射此数据类型,并进行一些调整。
PostgreSQL
假设新的数据类型在 postgres 数据库中的名称为 pg_new_type
。该名称必须映射到 DataTypes.SOMETYPE
。此外,还需要创建一个特定于 postgres 的子数据类型。
function createTheNewDataType() {
// [...]
const PgTypes = DataTypes.postgres;
// Mandatory: map postgres datatype name
DataTypes.SOMETYPE.types.postgres = ['pg_new_type'];
// Mandatory: create a postgres-specific child datatype with its own parse
// method. The parser will be dynamically mapped to the OID of pg_new_type.
PgTypes.SOMETYPE = function SOMETYPE() {
if (!(this instanceof PgTypes.SOMETYPE)) {
return new PgTypes.SOMETYPE();
}
DataTypes.SOMETYPE.apply(this, arguments);
}
const util = require('util'); // Built-in Node package
util.inherits(PgTypes.SOMETYPE, DataTypes.SOMETYPE);
// Mandatory: create, override or reassign a postgres-specific parser
// PgTypes.SOMETYPE.parse = value => value;
PgTypes.SOMETYPE.parse = DataTypes.SOMETYPE.parse || x => x;
// Optional: add or override methods of the postgres-specific datatype
// like toSql, escape, validate, _stringify, _sanitize...
}
范围
在 postgres 中定义了新的范围类型 后,将其添加到 Sequelize 很容易。
在本示例中,postgres 范围类型的名称为 SOMETYPE_range
,底层 postgres 数据类型的名称为 pg_new_type
。subtypes
和 castTypes
的键是 Sequelize 数据类型 DataTypes.SOMETYPE.key
的键,小写。
function createTheNewDataType() {
// [...]
// Add postgresql range, SOMETYPE comes from DataType.SOMETYPE.key in lower case
DataTypes.RANGE.types.postgres.subtypes.SOMETYPE = 'SOMETYPE_range';
DataTypes.RANGE.types.postgres.castTypes.SOMETYPE = 'pg_new_type';
}
新的范围可以在模型定义中用 DataTypes.RANGE(DataTypes.SOMETYPE)
或 DataTypes.RANGE(DataTypes.SOMETYPE)
使用。