公司項目須要實現館藏庫的全文檢索,可是隻有一個查詢,若是使用lucene的話不太方便,經過查找資料,發現oracle自帶全文檢索功能。通過測試,oracle實現全文檢索很方便,很實用。oracle
注意:本例子針對於表中某一字段的全文檢索。如ceshi表中name字段下全部數據的檢索。oop
環境:oracle11g,oracle鏈接爲search,表爲ceshi,字段有id,name測試
1:進行準備工做,oracle全文檢索須要ctxsys用戶的支持,其實主要須要使用ctxsys用戶下的ctx_ddl這個包,因此咱們使用system帳戶解鎖stxsys用戶。優化
1.1:使用system帳戶創建鏈接spa
1.2:解鎖stxsys用戶,分別執行如下兩個命令。並將權限賦予arc_master用戶(注意:arc_master用戶是我本身新建的用戶,可使用不一樣的用戶名).net
對ctxsys用戶解鎖,以得到ctx_ddl包的操做權。進入system用戶,輸入以下命令,解鎖ctxsys用戶blog
alter user ctxsys account unlock;排序
將ctx_ddl包的操做權限賦給arc_master用戶。索引
grant execute on ctx_ddl to arc_master; token
2:準備工做完成以後,使用arc_master用戶鏈接(鏈接如圖1),開始測試。
2.1:創建測試表
create table ceshi(
id number,
name varchar2(50)
);
2.2:插入測試數據
insert into ceshi values(111,'重慶市沙坪壩區');
insert into ceshi values(211,'成都市青羊區');
insert into ceshi values(311,'北京市西城區');
insert into ceshi values(411,'重慶市兩江新區');
insert into ceshi values(511,'上海市浦東新區金橋鎮');
insert into ceshi values(611,'上海東方明珠');
insert into ceshi values(711,'江蘇省無錫市國家軟件園');
insert into ceshi values(811,'成都市天府軟件園');
2.3:建立分析器,建立一個「chinese_lexer」分析器,名稱爲my_lexer。
exec ctx_ddl.create_preference ('my_lexer', 'chinese_vgram_lexer');
這個分析器的做用就是name字段的全部數據分詞,以便於後面建立索引。如圖所示:
詞法分析器有3種類型:
* 'CHINESE_VGRAM_LEXER'僅用於中文,提取標示符更大,無效標示符較多;
* 'CHINESE_LEXER' 僅用於中文,效率高一些更準確可靠一些;建議使用
* 'BASIC_LEXER'僅用於英文;
2.4:建立過濾詞組,,好比對公司名稱進行檢索時,確定不但願輸入「有限公司」、「公司」等關鍵詞時,也會有搜索結果。
exec ctx_ddl.create_stoplist('my_stoplist');
自定義須要過濾的詞組,建立了一個名爲「my_stoplist」的過濾詞組,「有限公司」、「股份有限公司」這兩個詞組不會被建立爲索引。
exec ctx_ddl.add_stopword('my_stoplist','有限公司');
exec ctx_ddl.add_stopword('my_stoplist','股份有限公司');
2.5:建立索引,在ceshi_INDEX表中的name字段上建立索引,索引類系那個爲context類型,該索引用到的分析器爲前面定義的my_lexer,該索引用到的過濾詞組爲前面定義得my_stoplist。
create index ceshi_INDEX on ceshi(name) indextype is CTXSYS.CONTEXT parameters('lexer my_lexer stoplist my_stoplist');
2.6:使用索引,此時的數據是沒有通過排序。經過如下的查詢語句就能夠很快的查處所需的內容。
select * from ceshi where contains(name,'北京市')>0;
2.7:雖然內容查出來了,不過數據是無序的。有的時候須要根據狀況決定查詢結果出現的前後順序。能夠按照關鍵字的匹配程度排序,這裏的score是oracle全文檢索對關鍵字的匹配程度所計算的分數,contains裏的最後一個參數「1」就是對這個分數的一個標識。
select score(1),y.* from ceshi y where contains(name,'軟件',1)>0 order by score(1) desc;
2.8:經過以上步驟基本就完成了oracle檢索。不過當咱們添加新數據的時候,新數據並無建立新的索引,此時須要索引同步和索引優化。
索引同步
exec ctx_ddl.sync_index('ceshi_index');
索引優化
exec ctx_ddl.optimize_index('ceshi_index','full');
3:最後一個問題,就是用戶輸入的關鍵字也須要進行分詞,由於前面分詞圖能夠看到,詞被分紅一塊一塊,若是用戶輸入的詞不拆分,有可能查不出來數據。(最後這一步驟的實現不理解)
首先須要先建立一個POLICY過程,這裏建立了一個名稱爲my_policy的policy過程,分析器用到了前面建立的my_lexer分析器
exec CTX_DDL.CREATE_POLICY('MY_POLICY', LEXER => 'my_lexer');
create or replace function p_split_chinese(p_input in varchar2)
return varchar2 as
v_tab CTX_DOC.TOKEN_TAB;
v_return VARCHAR2(323767);
begin
CTX_DOC.POLICY_TOKENS('my_policy',p_input,v_tab);
for i in 1..v_tab.count loop
v_return := v_return || ',' || v_tab[i].token;
end loop;
return LTRIM(v_return,',');
end;
select F_SPLIT_CHINESE('重慶天府') from dual;
F_SPLIT_CHINESE('重慶天府')
最後,經過這些步驟,咱們就能夠根據jdbc來實現功能了。
參考博文:http://blog.csdn.net/linfssay/article/details/7679353