oracle sql實現分詞搜索分詞功能

select * from t_zhzx_xjjq_new t where contains(t.bjnr,'有人車') > 0
create index qw_index_bjnr on t_zhzx_xjjq_new(bjnr) indextype is ctxsys.context

drop index ceshi_INDEX force

Begin
ctx_ddl.create_preference('my_lexer', 'chinese_lexer');
End

Begin
ctx_ddl.drop_preference('my_chinese_lexer');
End;

Create index IDX_TBL_COL on t_zhzx_xjjq_new (bjnr) indextype is ctxsys.context parameters ('lexer my_chinese_lexer');


-----------------
--對ctxsys用戶解鎖,以獲得ctx_ddl包的操作權。進入system用戶,輸入如下命令,解鎖ctxsys用戶

alter user ctxsys account unlock;

--將ctx_ddl包的操作權限賦給arc_master用戶。

--建立測試表

create table ceshi( 

id number, 

name varchar2(50) 

); 

--插入測試數據

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,'成都市天府軟件園');
commit;

--創建分析器,創建一個“chinese_lexer”分析器,名稱爲my_lexer。

exec ctx_ddl.create_preference ('my_lexer', 'chinese_lexer');

--這個分析器的作用就是name字段的所有數據分詞,以便於後面創建索引。如圖所示:

--創建過濾詞組,,比如對公司名稱進行檢索時,肯定不希望輸入“有限公司”、“公司”等關鍵詞時,也會有搜索結果。

exec ctx_ddl.create_stoplist('my_stoplist'); 

--自定義需要過濾的詞組,創建了一個名爲“my_stoplist”的過濾詞組,“有限公司”、“股份有限公司”這兩個詞組不會被創建爲索引。

exec ctx_ddl.add_stopword('my_stoplist','有限公司');

exec ctx_ddl.add_stopword('my_stoplist','股份有限公司'); 

exec ctx_ddl.drop_stoplist('my_stoplist');

--創建索引,在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');
--使用索引,此時的數據是沒有經過排序。通過以下的查詢語句就可以很快的查處所需的內容。

select * from ceshi where contains(name,'北京市')>0; 
--雖然內容查出來了,不過數據是無序的。有的時候需要根據情況決定查詢結果出現的先後順序。可以按照關鍵字的匹配程度排序,這裏的score是oracle全文檢索對關鍵字的匹配程度所計算的分數,contains裏的最後一個參數“1”就是對這個分數的一個標識。
select score(1),y.* from ceshi y where contains(name,'軟件',1)>0 order by score(1) desc; 
--通過以上步驟基本就完成了oracle檢索。不過當我們添加新數據的時候,新數據並沒有創建新的索引,此時需要索引同步和索引優化。

--索引同步

exec ctx_ddl.sync_index('ceshi_index');  --新增的數據之後必須執行該命令

--索引優化

exec ctx_ddl.optimize_index('ceshi_index','full');

--最後一個問題,就是用戶輸入的關鍵字也需要進行分詞,因爲前面分詞圖可以看到,詞被分成一塊一塊,如果用戶輸入的詞不拆分,有可能查不出來數據。(最後這一步驟的實現不理解)

--首先需要先創建一個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 p_split_chinese('我今天去上學,我到底是去還是不去呢') from dual;

F_SPLIT_CHINESE('重慶天府')

--最後,通過這些步驟,我們就可以根據jdbc來實現功能了。
-------------------------------------------------------------
select t.*, t.rowid from dr$ceshi_index$i t
insert into ceshi values ('222','我愛北京天安門')
select * from ceshi c where contains(c.name,p_split_chinese('江蘇省無錫市國家軟件園')) > 0
exec ctx_ddl.sync_index('ceshi_index');  --新增的數據之後必須執行該命令
select p_split_chinese('江蘇省無錫市國家軟件園') from dual;
--江蘇省  無錫  市  國家  軟件  園
select substr('or 江蘇省 or 無錫 or 市 or 國家 or 軟件 or 園',4) from dual;

----------------------------------------------------------------
--需要添加過濾關鍵詞時首先將索引刪除,然後在過濾詞組中添加過濾詞,之後重新創建索引:
drop index ceshi_INDEX force;
exec ctx_ddl.add_stopword('my_stoplist','有限公司');
create index ceshi_INDEX on ceshi(name) indextype is CTXSYS.CONTEXT parameters('lexer my_lexer stoplist my_stoplist');
exec ctx_ddl.sync_index('ceshi_index');  --新增的數據之後必須執行該命令
--查看過濾詞組中用哪些詞被過濾屏蔽:
SELECT * FROM CTX_USER_STOPLISTS;
SELECT * FROM CTX_USER_STOPWORDS;
--刪除過濾詞組中的某個過濾詞
exec ctx_ddl.remove_stopword('my_stoplist','道');
commit;

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章