2016-01-12 60 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

相關問題