跳到主要内容
版本:v6 - 稳定版

扩展数据类型

您试图实现的类型很可能已包含在 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_typesubtypescastTypes 的键是 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) 使用。