PostgreSQL 通常使用区分大小写的排序规则。这意味着每列中出现的数据都会与您的查询进行逐字比较。
您有多种选择:
1.按照 Ben 的回答,将包装列和数据库包装在 sequelize.fn('lower') 调用中。
优点:没有数据库更改。
缺点:您需要记住对每个查询都使用它。放弃索引(除非您已经创建了functional index)并按顺序扫描表,从而导致查找大型表的速度变慢。相当冗长的代码。
2。使用 ILIKE,不区分大小写地匹配模式
要准确查找名称:
Db.models.Person.findAll(where: {firstName: {$iLike: 'name'}});
要查找可能包含在任意字符中的片段:
Db.models.Person.findAll(where: {firstName: {$iLike: '%name%'}});
优点:容易记住。没有 Sequelize 函数包装器 - 它是一个内置运算符,因此语法更整洁。不需要特殊的索引或数据库更改。
缺点:速度慢,除非你开始弄乱pg_trgm 之类的扩展名
3.使用 citext 类型定义文本列,隐式比较小写
将您的列类型定义为“citext”(而不是text 或character varying)具有与此相同的实际效果:
select * from people where name = 'DAVID'
到这个...
select * from people where LOWER(name) = LOWER('DAVID')
PostgreSQL 文档显示了如何使用 citext 类型创建表的示例:
CREATE TABLE users (
nick CITEXT PRIMARY KEY,
pass TEXT NOT NULL
);
INSERT INTO users VALUES ( 'larry', md5(random()::text) );
INSERT INTO users VALUES ( 'Tom', md5(random()::text) );
INSERT INTO users VALUES ( 'Damian', md5(random()::text) );
INSERT INTO users VALUES ( 'NEAL', md5(random()::text) );
INSERT INTO users VALUES ( 'Bjørn', md5(random()::text) );
SELECT * FROM users WHERE nick = 'Larry';
TL;DR 基本上将您的“文本”列换成“citext”。
citext 模块与 PostgreSQL 8.4 捆绑在一起,因此无需安装任何扩展。但是您确实需要在使用以下 SQL 的每个数据库上启用它:
CREATE EXTENSION IF NOT EXISTS citext WITH SCHEMA public;
然后在您的 Sequelize 定义中,定义一个 type 属性:
// Assuming `Conn` is a new Sequelize instance
const Person = Conn.define('person', {
firstName: {
allowNull: false,
type: 'citext' // <-- this is the only change
}
});
那么您对该列的搜索将始终使用常规 where = 查询不区分大小写
优点:无需将您的查询包装在丑陋的 sequelize.fn 调用中。无需记住显式小写。区域设置感知,因此适用于所有字符集。
缺点:您需要记住在首次定义表时在 Sequelize 定义中使用它。始终处于激活状态 - 您需要知道在定义表格时要进行不区分大小写的搜索。