PostgreSQL全文檢索使用

1. Psql 安裝 (CentOS-7.x)

采用yum安裝psql是最簡潔高效的

# 更新一下yum
yum update -y
# 直接安裝 
yum install postgresql-server -y
# 初始化數(shù)據(jù)庫
postgresql-setup initdb
# 加入linux的服務(wù)管理
systemctl enable postgresql.service
# 啟動(dòng)服務(wù)
systemctl start postgresql.service

安裝完成之后,我們可能需要配置一下,Psql有兩個(gè)配置文件

/var/lib/pgsql/data/postgres.conf

如果你需要遠(yuǎn)程訪問,請(qǐng)取消注釋,并吧localhost改成*,我本地安裝,只為了自己平時(shí)使用,所以我就默認(rèn)監(jiān)聽localhost就可以了

postgres.conf
/var/lib/pgsql/data/pg_hba.conf

Psql 初始化過后,默認(rèn)提供一個(gè)postgres用戶和一個(gè)postgres數(shù)據(jù)庫,但是我們直接psql -U postgres -d postgres命令是連接不上的,因?yàn)樵谀J(rèn)配置里,當(dāng)前登錄的賬戶必須是postgres,才能連接

所以我們改一改,認(rèn)證方式改成md5或者password(不建議),默認(rèn)是沒有密碼的,所以要輸入密碼的時(shí)候,回車就好了

更粗暴的方式是直接把認(rèn)證方式改為trust,這樣凡是登錄到這臺(tái)電腦的用戶都被信任,個(gè)人電腦可以這么干了

更詳細(xì)的配置可以去看看官方文檔

pg_hba.conf

這個(gè)時(shí)候,我們重啟服務(wù),就可以登錄了

systemctl restart postgresql.service
psql -U postgres -h localhost -w

2. Psql 關(guān)于全文檢索的支持(tsvector和tsquery)

個(gè)人覺得,Psql對(duì)全文檢索還是很友好了,以前還是通過Apache Lucene實(shí)現(xiàn)的,最近看看Psql,簡單了不少

Psql 提供兩個(gè)數(shù)據(jù)類型tsvector,tsquery,并且通過動(dòng)態(tài)檢索自然語言文檔的集合,定位到最匹配的查詢結(jié)果

一個(gè)tsvector的值是唯一分詞的分類列表,把一話一句詞格式化為不同的詞條,在進(jìn)行分詞處理的時(shí)候,tsvector會(huì)自動(dòng)去掉分詞中重復(fù)的詞條,按照一定的順序裝入,例如

# psql的自動(dòng)分詞(默認(rèn)是英文分詞,中文分詞后面講)
select 'hello world'::tsvector;
# 輸出
tsvector
-----------------------------
'hello' 'world'

# 可以設(shè)置詞條位置常量
select 'hello:3 world:1'::tsvector;
# 輸出
tsvector
-----------------------------
'hello':3 'world':1

這個(gè)位置信息通常就是當(dāng)前文檔中單詞所處的位置,這個(gè)位置信息用于關(guān)注度的體現(xiàn)。位置信息常量的值的范圍為1 到 16383。分詞后,會(huì)把相同詞條的位置記錄到一個(gè)詞條中

tsquery,相當(dāng)于是查詢tsvector的查詢條件,并且可以聯(lián)合使用boolean 操作符來連接, & (AND), | (OR), and ! (NOT). 使用括號(hào)(),可以強(qiáng)制分為一組
在全文檢索的過程中,tsquerytsvector之間采用@@操作符

select 'hello world fuck you hahahaha'::tsvector @@ 'hello & you'::tsquery;
?column? 
------------------
t

對(duì)于英文全文檢索應(yīng)用來說,很多時(shí)候的句子是非標(biāo)準(zhǔn)化的,但是tsvector和tsquery是不會(huì)知道的,為處理加工的文本應(yīng)該通過使用to_tsvector函數(shù)

# 采用psql提供的函數(shù)幫助我們將文本分詞
select to_tsvector('hello world');
to_tsvector     
---------------------
 'hello':1 'world':2

# 采用psql提供的函數(shù)進(jìn)行全文檢索
select to_tsvector('hello world fuck you hahah') @@ to_tsquery('hello & you');
?column? 
------------------
t

在Psql中 @@操作符會(huì)將兩邊的文本進(jìn)行自動(dòng)的轉(zhuǎn)換

  • tsvector @@ tsquery
  • text @@ tsquery
  • text @@ text
  • 后兩種,text @@ tsquery 等同于 to_tsvector(x) @@ y.
  • 而 text @@ text 等同于 to_tsvector(x) @@ plainto_tsquery(y).

plainto_tsquery() 用于將文本轉(zhuǎn)為tsquery,這樣就不用每次都去寫 & 條件了

3. Psql 索引類型

我們也要為全文檢索建立索引,提升查詢效率,我們?yōu)槿臋z索建立的索引是Gin索引

幾種基本索引類型

B-Tree
CREATE INDEX test1_id_index ON test1 (id);

B-Tree索引主要用于等于和范圍查詢,特別是當(dāng)索引列包含操作符" <、<=、=、>=和>"作為查詢條件時(shí),PostgreSQL的查詢規(guī)劃器都會(huì)考慮使用B-Tree索引。在使用BETWEEN、IN、IS NULL和IS NOT NULL的查詢中,PostgreSQL也可以使用B-Tree索引(MySQL則不會(huì))。然而對(duì)于基于模式匹配操作符的查詢,如LIKE、ILIKE、~和 ~*,僅當(dāng)模式存在一個(gè)常量,且該常量位于模式字符串的開頭時(shí),如col LIKE 'foo%'或col ~ '^foo',索引才會(huì)生效,否則將會(huì)執(zhí)行全表掃描,如:col LIKE '%bar'。

Hash
CREATE INDEX name ON table USING hash (column);

散列(Hash)索引只能處理簡單的等于比較。當(dāng)索引列使用等于操作符進(jìn)行比較時(shí),查詢規(guī)劃器會(huì)考慮使用散列索引。

這里需要額外說明的是,PostgreSQL散列索引的性能不比B-Tree索引強(qiáng),但是散列索引的尺寸和構(gòu)造時(shí)間則更差。另外,由于散列索引操作目前沒有記錄WAL日志,因此一旦發(fā)生了數(shù)據(jù)庫崩潰,我們將不得不用REINDEX重建散列索引。

GiST
CREATE INDEX name ON table USING gist (column);

GiST索引不是一種單獨(dú)的索引類型,而是一種架構(gòu),可以在該架構(gòu)上實(shí)現(xiàn)很多不同的索引策略。從而可以使GiST索引根據(jù)不同的索引策略,而使用特定的操作符類型。

GIN
CREATE INDEX name ON table USING gin (column);

GIN索引是反轉(zhuǎn)索引,它可以處理包含多個(gè)鍵的值(比如數(shù)組)。與GiST類似,GIN同樣支持用戶定義的索引策略,從而可以使GIN索引根據(jù)不同的索引策略,而使用特定的操作符類型。作為示例,PostgreSQL的標(biāo)準(zhǔn)發(fā)布中包含了用于一維數(shù)組的GIN操作符類型,如:<@、@>、=、&&等。

兩種建立索引方式
# 我新建一個(gè)posts表,記錄我的博客內(nèi)容,平時(shí)需要根據(jù)博客名和內(nèi)容做查詢
create table posts (
  id integer,
  title varchar(50) not null,
  content text not null,
  primary key(id)
);
  1. 為tsv函數(shù)建索引
create index post_tsvcontent_idx on posts using gin(to_tsvector('english', title || content));
  1. 新增一個(gè)tsv列,為列建立索引(推薦)
alter table posts add_column tsv_content tsvector;
update posts set tsv_content = to_tsvector('english', coalesce(title,'') || coalesce(content,''));
create index post_tsvcontent2_idx on posts using gin(tsv_content);

現(xiàn)在都可以對(duì)posts表里的內(nèi)容進(jìn)行全文檢索了

# 例如
select title from posts where to_tsvector(title || content) @@ plainto_tsquery('hello world');

# 或者
select title from posts where tsv_content @@ plainto_tsquery('hello world');

4. 用觸發(fā)器更新分詞字段

如果我們是單獨(dú)新建一列去存放tsvector的分詞內(nèi)容,為了簡便,我們希望在插入記錄過后,自動(dòng)對(duì)需要檢索的列生成分詞,所以我們就需要觸發(fā)器

# Psql 提供了兩個(gè)觸發(fā)器函數(shù)用于實(shí)現(xiàn)此功能
tsvector_update_trigger()    
tsvector_update_trigger_column()
# 當(dāng)然,你也可以寫自己的觸發(fā)器
tsvector_update_trigger() 的使用
# 非常簡單
CREATE TRIGGER trigger_posts_tsv_content BEFORE INSERT OR UPDATE 
ON posts FOR EACH ROW EXECUTE PROCEDURE
tsvector_update_trigger(tsv_content, 'english', title, content)

5. 采用zhparser支持中文分詞

zhparser是基于Simple Chinese Word Segmentation(SCWS)中文分詞庫實(shí)現(xiàn)的一個(gè)PG擴(kuò)展,作者是 amutu,源碼URL為https://github.com/amutu/zhparser

安裝SCWS
wget -q -O - http://www.xunsearch.com/scws/down/scws-1.2.2.tar.bz2 | tar xf -
cd scws-1.2.2
./configure
make install
安裝zhparser
git clone https://github.com/amutu/zhparser.git
cd zhparser
SCWS_HOME=/usr/local make && make install
配置zhparser擴(kuò)展
# 連接到目標(biāo)數(shù)據(jù)庫,創(chuàng)建zhparser解析器
create extension zhparser
# 將zhparser解析器作為全文檢索配置項(xiàng)
create text search configuration chinese (PARSER = zhparser);

然后通過\dF和\dFp命令查看配置

demo
指定分詞策略

zhparser可以將中文切分成下面26種token

# 連接到目標(biāo)數(shù)據(jù)庫
select ts_token_type('zhparser');
demo

普遍情況下,我們只需要按照名詞(n),動(dòng)詞(v),形容詞(a),成語(i),嘆詞(e)和習(xí)用語(l)6種方式對(duì)句子進(jìn)行劃分就可以了,詞典使用的是內(nèi)置的simple詞典,即僅做小寫轉(zhuǎn)換

所以添加如下映射

alter text search configuration chinese add mapping for n,v,a,i,e,l with simple;
最后效果
# 連接到目標(biāo)數(shù)據(jù)庫
select to_tsvector('chinese', '這周日你有空么');
# 輸出
to_tsvector 
-------------------------
'么':2 '有空':1
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 之前的文章一直在規(guī)避索引的建立去優(yōu)化數(shù)據(jù)庫,不是不想講,而是這個(gè)太重要,必須抽出來講。今天我們就來研究下數(shù)據(jù)庫索引...
    JackFrost_fuzhu閱讀 4,814評(píng)論 0 70
  • 在項(xiàng)目中如果要實(shí)現(xiàn)全文檢索,最普通的方法就是通過數(shù)據(jù)庫查詢語句like '%keywords%',但是這種方法在數(shù)...
    xsg閱讀 8,173評(píng)論 2 2
  • 目錄結(jié)構(gòu):1.全文檢索 2.Lucene入門3.Lucene進(jìn)階 全文檢索 一, 生活中的搜索:1.Win...
    CoderZS閱讀 1,798評(píng)論 0 12
  • 概述 postgresql是一個(gè)開源的關(guān)系型數(shù)據(jù)庫,可以作為mysql的替代品。本篇意在讓讀者快速的了解postg...
    胖頭魚狂戰(zhàn)士閱讀 8,593評(píng)論 0 7
  • 周一的時(shí)候翹課,寫了一天代碼,收獲頗豐。周二的時(shí)候翹課,看了一天動(dòng)漫,收獲頗豐。 終于有點(diǎn)癡迷于一樣?xùn)|西的感覺了,...
    餌心閱讀 217評(píng)論 0 0

友情鏈接更多精彩內(nèi)容