How to use the lowercase function in Sequelize Postgres

I am trying to use a string function to search for strings in Sequelize. I manage to do this using ilike. My question is how to use a string function in this scenario?

findAll Using ilike is as follows:

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

How do I change it to lower(firstname) = lower('somename');

+6
source share
2 answers

PostgreSQL typically uses case-sensitive mappings. This means that the data that appears in each column is compared literally with your query.

You have several options:


1. Follow Ben's answer and wrap your columns and database in a call to sequelize.fn('lower') .

Pros: no changes to the database.

Cons: you need to remember to use it for every request. Foregoes indexes (if you have not already created a functional index) and consecutively scan tables, which leads to a slower scan with large tables. Pretty detailed code.


2. Use ILIKE to insensitive to pattern

To find the name exactly:

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

To find a fragment that can be contained within arbitrary characters:

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

Pros: easy to remember. No Sequelize wrapper is a built-in statement, so the syntax is more accurate. No special indexes or database changes are required.

Cons: Slowly unless you start messing with extensions like pg_trgm


3. Define your text columns with a citext type that implicitly compares lowercase

Defining column types as "citext" (instead of text or character varying ) has the same practical effect:

select * from people where name = 'DAVID'

to that...

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

The PostgreSQL documentation shows this as an example of how to create a table of type 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 basically replaces your text columns with citext.

The citext module comes bundled with PostgreSQL 8.4, so there is no need to install any extensions. But you need to include it in every database that you use with the following SQL:

CREATE EXTENSION IF NOT EXISTS citext WITH SCHEMA public;

And then in the Sequelize definitions, define the type attribute:

 // Assuming `Conn` is a new Sequelize instance const Person = Conn.define('person', { firstName: { allowNull: false, type: 'citext' // <-- this is the only change } }); 

Then your search queries against this column will always be case insensitive with regular queries where =

Pros: No need to wrap your queries in ugly sequelize.fn calls. No need to remember clearly lowercase letters. Knowledge of the locale, therefore, works in all character sets.

Cons: You must remember to use it in your Sequelize definitions when you first define your table. Always activated - you need to know that when defining tables, you will need to do a case-insensitive search.

+14
source

You can use the built-in functions in the where clause:

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

which translates to

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

All Articles