如何在Sequelize Postgres中使用小写函数

spy*_*t01 12 postgresql node.js sequelize.js

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

findAll使用ILIKE是如下:

Db.models.Person.findAll(where: {firstName: {$ilike: `somename`}});
Run Code Online (Sandbox Code Playgroud)

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

Lee*_*son 25

PostgreSQL通常使用区分大小写的排序规则.这意味着每列中显示的数据将根据您的查询进行字面比较.

你有几个选择:


1.按照Ben的回答,将你的包裹列和数据库包装在一个sequelize.fn('lower')电话中.

优点:没有数据库更改.

缺点:您需要记住每次查询都使用它.Foregoes索引(除非您已经创建了功能索引)并按顺序扫描表,导致大表的查找速度变慢.相当冗长的代码.


2.使用ILIKE,以区分大小写匹配模式

要准确找到名称:

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

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

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

优点:易于记忆.No Sequelize函数包装器 - 它是一个内置的运算符,因此语法更整洁.无需特殊索引或数据库更改.

缺点:慢,除非你开始搞乱像pg_trgm这样的扩展


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

将列类型定义为"citext"(而不是textcharacter 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';
Run Code Online (Sandbox Code Playgroud)

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
  }
});
Run Code Online (Sandbox Code Playgroud)

然后,对该列的搜索将始终对常规where =查询不区分大小写

优点:无需将您的查询包装在丑陋的sequelize.fn调用中.无需记住显式小写.可识别区域设置,因此适用于所有字符集.

缺点:首次定义表时,您需要记住在Sequelize定义中使用它.始终激活 - 您需要知道在定义表时您需要进行不区分大小写的搜索.


小智 7

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

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

这将转化为

select * from person where lower(firstname) = lower('somename');
Run Code Online (Sandbox Code Playgroud)

  • @Ben:这对我不起作用,我建议:`where:{phoneNumber:'8435551212',$ col:sequelize.where(sequelize.fn('lower',sequelize.col('firstname')),sequelize。 fn('lower','somename'))}` (2认同)