如何在 Sequelize Postgres 中使用 Lowercase 函数

How to use Lowercase function in Sequelize Postgres

我正在尝试使用小写函数在 Sequelize 中进行字符串搜索。 我设法使用 ilike 来做到这一点。 我的问题是在这种情况下如何使用小写函数?

使用ilike的findAll如下:

Db.models.Person.findAll(where: {firstName: {$ilike: `somename`}});

如何更改为lower(firstname) = lower('somename');

您可以在 where 子句中使用本机函数:

Db.models.Person.findAll({
  where: sequelize.where(
    sequelize.fn('lower', sequelize.col('firstname')), 
    sequelize.fn('lower', 'somename')
  )
});

这将转化为

select * from person where lower(firstname) = lower('somename');

PostgreSQL 通常使用 case-sensitive 归类。这意味着每列中显示的数据都会与您的查询逐字比较。

您有多种选择:


1.按照 Ben 的回答,将包装列和数据库包装在 sequelize.fn('lower') 调用中。

优点:没有数据库更改。

缺点:您需要记住在每个查询中使用它。放弃索引(除非您已经创建了 functional index)并按顺序扫描 tables,导致 look-ups 变慢且 tables 变大。相当冗长的代码。


2。使用 ILIKE,case-insensitively 匹配模式

准确查找姓名:

Db.models.Person.findAll(where: {firstName: {$iLike: 'name'}});

要查找可能包含在任意字符中的片段:

Db.models.Person.findAll(where: {firstName: {$iLike: '%name%'}});

优点:容易记住。没有 Sequelize 函数包装器——它是一个 built-in 运算符,所以语法更简洁。无需特殊索引或数据库更改。

缺点:速度慢,除非你开始搞乱像 pg_trgm

这样的扩展

3。使用 citext 类型定义文本列,该类型隐式比较小写

将您的列类型定义为 'citext'(而不是 textcharacter varying)具有与以下相同的实际效果:

select * from people where name = 'DAVID'

对此...

select * from people where LOWER(name) = LOWER('DAVID')

PostgreSQL 文档将其显示为如何使用 citext 类型创建 table 的示例:

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 基本上将 "text" 列换成 "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
  }
});

那么您对该列的搜索将总是 case-insensitive 与常规 where = 查询

优点:无需将查询包装在丑陋的 sequelize.fn 调用中。无需记住明确小写。区域设置感知,因此适用于所有字符集。

缺点:您需要记住在第一次定义 table 时在 Sequelize 定义中使用它。始终激活 - 您需要知道在定义 tables.

时要进行不区分大小写的搜索