Oracle的全文檢索,以前用過,效果還可以,就是耗資源。
現在這裏也在考慮使用全文檢索,自己印象中有兩種:
1. Oracle的全文檢索(CTX),雖然其他數據庫也有全文檢索,不過這裏用的是Oracle,也就看看Oracle的全文檢索 --- 以前用的全文檢索也是Oracle,正好數據庫一樣;
2. Apache基金會的Lucene, 後續有企業級升級版應用 Solr
Lucene以前也用過,Solr沒有用過;
以前用Lucene的時候,Solr還沒有出現,在多機使用同一套Lucene索引貌似還有一定講究,時間長了,不記得了。
這裏先抄一篇對Oracle全文檢索講的比較清晰的文章(以前用過,所以一看簡單說明,全部能記起來)
http://blog.itpub.net/10597729/viewspace-741700/
其實這篇文章也是轉載ITPUT論壇上的一篇文章
轉載自:http://www.iteye.com/topic/1118055
1.oracle text
首先這裏說oracle 全文檢索,是針對我機器上的oracle 10g版本的。至少 10g 或以上的版本 適合這樣來使用。
oracle 的全文檢索,操作步驟爲:將表中需要檢索的字段,創建爲全文檢索的索引,然後通過select * from T where contains(F,'test',1)>0的語句進行全文檢索,達到預期效果。
然後,oracle全文檢索還是很強大的,能夠檢索文本啊、還有其他多種格式的文檔。我做的測試只是針對數據庫中的某一個字段的檢索。比如針對地址表中的地址進行檢索。
2.準備操作
首先,先建一個表用於測試,在名爲testuser用戶下建表。
- create table YU_TEST(
- id number,
- name varchar2(50)
- );
插入測試數據
- insert into YU_TEST values(1,'重慶市沙坪壩區');
- insert into YU_TEST values(2,'成都市青羊區');
- insert into YU_TEST values(3,'北京市西城區');
- insert into YU_TEST values(4,'重慶市兩江新區');
- insert into YU_TEST values(5,'上海市浦東新區金橋鎮');
- insert into YU_TEST values(6,'上海東方明珠');
- insert into YU_TEST values(7,'江蘇省無錫市國家軟件園');
- insert into YU_TEST values(8,'成都市天府軟件園');
oracle全文檢索需要ctxsys用戶的支持,其實主要是需要使用ctxsys用戶下的ctx_ddl這個包,這個包中絕大部分過程的創建都與全文檢索有關。
首先需要對ctxsys用戶解鎖,以獲得ctx_ddl包的操作權。
進入system用戶,輸入如下命令,解鎖ctxsys用戶
- alter user ctxsys account unlock;
然後將ctx_ddl包的操作權限賦給testuser用戶。
也是在system用戶下,輸入如下命令,賦予目標用戶ctx_ddl包操作權限
- grant execute on ctx_ddl to testuser;
至此,準備工作已經完成了
3.創建分析器
oracle text的分析器,類似於lucene中的分詞器,將需要檢索的記錄,按照一定的方式進行詞組拆分,然後存放在索引表中。檢索的時候根據索引表中存放的拆分詞組,對傳入的關鍵字進行匹配,並返回匹配結果。
oracle text中的分析器有3種:
- basic_lexer:只能根據空格和標點來進行拆分。比如“中國重慶”,只能拆分爲“中國重慶”一個詞組
- chinese_vgram_lexer:專門的漢語分析器,按字單元進行拆分,比如“中國重慶”,可以拆分爲“中”、“中國“、”國重”、“重慶”、“慶”五個詞組。這種方式的好處是能夠將所有有可能的詞組全部保存進索引表,使得數據不會遺漏。
- chinese_lexer:一種新的漢語分析器,能夠認識大部分常用的漢語詞彙,並按常用詞彙進行拆分存儲。比如“中國重慶”,只會被拆分爲“中國”、“重慶”兩個詞組。
這裏我使用chinese_lexer這個分詞器,用testuser用戶登錄,執行下面的命令,創建分析器。
- exec ctx_ddl.create_preference ('my_lexer', 'chinese_lexer');
這句話的意思是,創建一個“chinese_lexer”分析器,名稱爲my_lexer。
4.創建過濾詞組
在我們建索引的時候,通常需要對一些常用的詞組進行過濾,比如對公司名稱進行檢索時,肯定不希望輸入“有限公司”、“公司”等關鍵詞時,也會有搜索結果。
用testuser用戶登錄,執行下面的命令,創建過濾詞組
- exec ctx_ddl.create_stoplist('my_stoplist');
創建過濾詞組成功以後,需要自定義需要過濾的詞組
- ctx_ddl.add_stopword('my_stoplist','有限公司');
- ctx_ddl.add_stopword('my_stoplist','股份有限公司');
意思就是,創建了一個名爲“my_stoplist”的過濾詞組,“有限公司”、“股份有限公司”這兩個詞組不會被創建爲索引
5.創建索引
其實前面的工作,都是爲創建索引做準備的。
我要對YU_TEST表中的name字段進行檢索,首先必須對name字段創建索引。
這裏需要注意的是,name字段不能爲nvarchar2類型,並且這個表的主鍵也不能爲nvarchar2型,否則無法創建索引。
- create index YU_TEST_INDEX on YU_TEST(name) indextype is CTXSYS.CONTEXT parameters('lexer my_lexer stoplist my_stoplist');
這句話的意思就是,在YU_TEST_INDEX表中的name字段上創建索引,索引類系那個爲context類型,該索引用到的分析器爲前面定義的my_lexer,該索引用到的過濾詞組爲前面定義得my_stoplist。
索引創建成功後,你回發現,在當前用戶的表中,多了四個表
其中YU_TEST表中name字段被拆分後的詞組保存在DR$YU_TEST_INDEX$I表中
這樣可以看見索引的詳細信息。
6.使用索引
- select * from YU_TEST where contains(name,'重慶')>0;
- select score(1),y.* from YU_TEST y where contains(name,'重慶',1)>0 order by score(1) desc;
- exec ctx_ddl.sync_index('yu_test_index')
- exec ctx_ddl.optimize_index('yu_test_index','full')
- 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;
- /
可以看到這裏顯示的只有“天府”相關的信息,那麼“重慶”相關的呢?