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

Node.js 如何在Sequelize Postgres中使用小写函数,node.js,postgresql,sequelize.js,Node.js,Postgresql,Sequelize.js,我正在尝试使用小写函数在Sequelize中进行字符串搜索。 我设法用ilike做这件事。 我的问题是在这种情况下如何使用小写函数 使用ilike的findAll如下所示: Db.models.Person.findAll(where: {firstName: {$ilike: `somename`}}); 如何将其更改为lowerfirstname=lower'somename' 您可以在where子句中使用本机函数: Db.models.Person.findAll({ where:

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

使用ilike的findAll如下所示:

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

如何将其更改为lowerfirstname=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通常使用区分大小写的排序规则。这意味着会将每列中显示的数据与查询进行逐字比较

您有几个选择:

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

优点:没有数据库更改

缺点:您需要记住对每个查询都使用它。放弃索引,除非您已经创建了索引并按顺序扫描表,否则会导致查找大型表的速度变慢。相当冗长的代码

二,。使用ILIKE不区分大小写地匹配模式

要准确查找名称,请执行以下操作:

Db.models.Person.findAllwhere:{firstName:{$iLike:'name'}

要查找可能包含在任意字符中的片段,请执行以下操作:

Db.models.Person.findAllwhere:{firstName:{$iLike:'%name%'}

优点:容易记住。没有Sequelize函数包装器-它是一个内置操作符,因此语法更简洁。不需要特殊的索引或数据库更改

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

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

将列类型定义为“citext”而不是文本或字符变化具有相同的实际效果:

从姓名为'DAVID'的人员中选择*

对此

从LOWERname=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的每个数据库上启用它:

如果不存在架构为public的citext,则创建扩展

然后在Sequelize定义中定义类型属性:

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

不知道这是否适用于您,但在我的例子中,我尝试在C linq中使用uncent函数,但无法使其工作,最后只需创建一个新列u_列并使用postgres函数填充它。用这种方法,当我需要搜索多个参数时,我应该怎么做呢。例如:姓氏和电话号码。其中lastName与firstName类似,phoneNumber是一个存储数字的字段。您只需将它们作为普通添加到where:{}对象中即可。where:{sequelize.wheresequelize.fn'lower',sequelize.col'firstname',sequelize.fn'lower',somename',phoneNumber:843555212}@Ben:这对我不起作用,我建议:where:{phoneNumber:'843555212',col col sequelize.wheresequelize.fn'lower',sequelize.col firstname',sequelize.fn'lower somename'}我通过以下迁移完成了第三个解决方案。可能对其他人有用:module.exports={up:function queryInterface,Sequelize{queryInterface.Sequelize.query'CREATE EXTENSION IF NOT EXISTS citext WITH SCHEMA public;';queryInterface.Sequelize.query'CREATE TABLE mytableemail citext主键不为NULL,密码文本不为NULL;;},向下:函数queryInterface,Sequelize{queryInterface.dropTable'mytable';};Re 2:如果名称中的特殊字符来自用户,则可能需要额外的代码来转义。我想知道有人通常会如何设计不区分大小写的搜索,但有时仍然选择区分大小写的匹配。我们是否需要在应用程序代码中进行第二次传递以应用大小写敏感度,或者是否有一个SQL运算符意味着这一次,即使此字段是citext,也要遵守大小写?citext imho的另一个缺点是,它不能与字段的maxlength组合!另外,在使用停靠的psql数据库时,正确设置它是相当麻烦的,但这可能是一件单独的事情。