2016-01-12 59 views
6

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

findAll是如下:

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

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

+0

不知道是否适用于你,但在我的情况下,我尝试使用在C#中的LINQ unaccent功能并且不可能使它工作,在刚刚结束创建新列'u_column'和使用Postgres的函数来填充它。没有preatty但工作。 –

回答

13

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

您有几种选择:


1.按照本的答案,并包裹在一个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。

select * from people where name = 'DAVID'

:与citext类型,它隐含比较小写

定义列类型为“citext”(而不是textcharacter varying)有把这个相同的实际效果定义你的文本列

这个...

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

PostgreSQL的documen塔季翁表示这是一个如何与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定义首先定义表时。始终激活 - 您需要知道在定义表格时您需要执行不区分大小写的搜索。

+0

我通过以下迁移完成了第三个解决方案。可能为其他有用:module.exports = { 起来:函数(的QueryInterface,Sequelize){ queryInterface.sequelize.query( '创建扩展IF NOT存在具有SCHEMA公共citext;'); (''CREATE TABLE mytable(email CITEXT PRIMARY KEY NOT NULL,password TEXT NOT NULL);'); }, 向下:函数(的QueryInterface,Sequelize){ 的QueryInterface。DROPTABLE( 'MYTABLE'); } }; – Andreas

2

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

使用这种方式,当我需要搜索多个参数时,我应该怎么做。 例如:姓氏和电话号码。 lastName是类似于firstName的字段类型,phoneNumber是存储数字的字段。 – spyalert01

+0

您只需将它们正常添加到您的'where:{}'对象。 '其中:{ sequelize.where(sequelize.fn( '低',sequelize.col( '姓名')),sequelize.fn( '下', 'somename')), 电话号码:8435551212 }' –

+1

@Ben:这不是为我工作,我建议:'其中:{电话号码: '8435551212',$西:sequelize.where(sequelize.fn( '下',sequelize.col( '名字')),sequelize .fn('lower','somename'))}' – kwarnke

相关问题