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

时间:2016-01-12 21:44:43

标签: node.js postgresql sequelize.js

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

使用ilike的findAll如下:

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

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

2 个答案:

答案 0 :(得分:22)

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

您有几种选择:

<强> 1。按照Ben的回答,将您的包裹列和数据库打包在sequelize.fn('lower')电话中。

优点:没有数据库更改。

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

<强> 2。使用ILIKE,不区分大小写匹配模式

要准确找到名称:

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

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

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

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

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

这样的扩展

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

将列类型定义为&#39; citext&#39; (而不是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';

TL; DR基本上换掉你的&#34;文本&#34; &#34; citext&#34;。

的列

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定义中使用它。始终激活 - 您需要知道在定义表时您将要进行不区分大小写的搜索。

答案 1 :(得分:6)

您可以在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');