Oracle的全文檢索技術(轉)

zhouwf0726發表於2019-05-15
Oracle一直致力於全文檢索技術的研究,當Oracle9i Rlease2釋出之時,Oracle資料庫的全文檢索技術已經非常完美,Oracle Text使Oracle9i具備了強大的文字檢索能力和智慧化的文字管理能力。Oracle Text是Oracle9i採用的新名稱,在Oracle8/8i中它被稱作Oracle interMedia Text。使用Oracle Text,可以方便而有效地利用標準的SQL工具來構建基於文字的新的開發工具或對現有應用程式進行擴充套件。應用程式開發人員可以在任何使用文字的Oracle資料庫應用程式中充分利用Oracle Text搜尋,應用範圍可以是現有應用程式中可搜尋的註釋欄位,也可是實現涉及多種文件格式和複雜搜尋標準的大型文件管理系統。Oracle Text支援Oracle資料庫所支援的大多數語言的基本全文搜尋功能。
雖然大多數大型資料庫都支援全文檢索,但Oracle在這方面無疑是最出色的。Oracle能搜尋多種格式的文件,如Word,Execl,PowerPoint,Html,PDF等等。但在使用中也發現有遺憾的地方,Oracle Text無論使用何種過濾器(INSO_FILTER或NULL_FILTER)及何種詞法分析器(BASIC_LEXER, CHINESE_VGRAM_LEXER還是CHINESE_LEXER)都不能檢索出中文內容的文字文件(TXT,RTF)。


1 Oracle Text的體系架構

下圖是Oracle Text的體系架構:

圖1 Oracle Text的體系架構

Oracle Text 索引文件時所使用的主要邏輯步驟如下:

  (1)資料儲存邏輯搜尋表的所有行,並讀取列中的資料。通常,這只是列資料,但有些資料儲存使用列資料作為文件資料的指標。例如,URL_DATASTORE 將列資料作為 URL 使用。如果對本地檔案進行檢索,只要指定DATASTORE中FILE_DATASTORE引數為檔案的路徑即可。

  (2)過濾器提取文件資料並將其轉換為文字表示方式。儲存二進位制文件 (如 Word 或 Acrobat 檔案) 時需要這樣做。過濾器的輸出不必是純文字格式 -- 它可以是 XML 或 HTML 之類的文字格式。

  (3)分段器提取過濾器的輸出資訊,並將其轉換為純文字。包括 XML 和 HTML 在內的不同文字格式有不同的分段器。轉換為純文字涉及檢測重要文件段標記、移去不可見的資訊和文字重新格式化。

  (4)詞法分析器提取分段器中的純文字,並將其拆分為不連續的標記。既存在空白字元分隔語言使用的詞法分析器,也存在分段複雜的亞洲語言使用的專門詞法分析器。

  (5)索引引擎提取詞法分析器中的所有標記、文件段在分段器中的偏移量以及被稱為非索引字的低資訊含量字列表,並構建反向索引。倒排索引儲存標記和含有這些標記的文件。


歸納起來如下:

  (1)建表並裝載文字(包含帶有需要檢索的文字欄位)

  (2)配置索引

  (3)建立索引

  (4)發出查詢

  (5)索引維護:同步與優化(將在後面介紹)

 文字裝載

  要實現文字的全文檢索首先必須把正確的文字載入到資料庫表中,預設的建立索引行為要求將文件裝載在文字列中,儘管可以用其它方式 (包括檔案系統和 URL 形式)儲存文件 (在"資料儲存"選項進行設定)。預設情況下,系統應該將文件裝載在文字列中。文字列可以是VARCHAR2、CLOB、BLOB、CHAR或BFILE。注意,只有在將Oracle7系統移植到Oracle8的情況下才支援用LONG和LONG RAW 這兩個相反的列型別儲存文字。不能為列型別NCLOB、DATE和NUMBER建立索引。

  關於文件格式,因為系統能為包括HTML、PDF、Microsoft Word和純文字在內的大多數文件格式建立索引,可以將其中的任何文件型別裝載到文字列中(在"過濾器"選項中設定)。有關所支援的文件格式的詳細資訊,可以參閱Oracle Text User's Guide and Reference 中的附錄"Supported Filter Formats"。

  裝載方法主要有以下幾種:

  (1)SQL INSERT 語句

  (2)ctxload 可執行檔案

  (3)SQL*Loader

  (4)從 BFILE 中裝載 LOB 的 DBMS_LOB.LOADFROMFILE() PL/SQL 過程

  (5)Oracle Call Interface


 建立索引

  文字裝入文字列後,就可以建立Oracle Text索引。文件以許多不同方案、格式和語言儲存。因此,每個 Oracle Text 索引有許多需要設定的選項,以針對特定情況配置索引。建立索引時,Oracle Text可使用若干個預設值,但在大多數情況下要求使用者通過指定首選項來配置索引。

  每個索引的許多選項組成功能組,稱為"類",每個類集中體現配置的某一方面,可以認為這些類就是與文件資料庫有關的一些問題。例如:資料儲存、過濾器、詞法分析器、相關詞表、儲存等。

  每個類具有許多預定義的行為,稱之為物件。每個物件是類問題可能具有的答案,並且大多數物件都包含有屬性。通過屬性來定製物件,從而使對索引的配置更加多變以適應於不同的應用。

  (1)儲存(Storage)類

  儲存類指定構成Oracle Text索引的資料庫表和索引的表空間引數和建立引數。它僅有一個基本物件:BASIC_STORAGE,其屬性包括:I_Index_Clause、I_Table_Clause、K_Table_Clause、N_Table_Clause、P_Table_Clause、R_Table_Clause。

  (2)資料儲存(Datastore)類

  資料儲存:關於列中儲存文字的位置和其他資訊。預設情況下,文字直接儲存到列中,表中的每行都表示一個單獨的完整文件。其他資料儲存位置包括儲存在單獨檔案中或以其 URL 標識的 Web 頁上。七個基本物件包括:Default_Datastore、Detail_Datastore、Direct_Datastore、File_Datastore、Multi_Column_Datastore 、URL_Datastore、User_Datastore,。

  (3)文件段組(Section Group)類

  文件段組是用於指定一組文件段的物件。必須先定義文件段,然後才能使用索引通過 WITHIN 運算子在文件段內進行查詢。文件段定義為文件段組的一部分。包含七個基本物件:AUTO_SECTION_GROUP、BASIC_SECTION_GROUP、HTML_SECTION_GROUP、NEWS_SECTION_GROUP、NULL_SECTION_GROUP、XML_SECTION_GROUP、PATH_SECTION_GROUP。

  (4)相關詞表(Wordlist)類

  相關詞表標識用於索引的詞幹和模糊匹配查詢選項的語言,只有一個基本物件BASIC_WORDLIST,其屬性有:Fuzzy_Match、Fuzzy_Numresults、Fuzzy_Score、Stemmer、Substring_Index、Wildcard_Maxterms、Prefix_Index、Prefix_Max_Length、Prefix_Min_Length。

  (5)索引集(Index Set)

  索引集是一個或多個Oracle 索引 (不是Oracle Text索引) 的集合,用於建立 CTXCAT型別的Oracle Text索引,只有一個基本物件BASIC_INDEX_SET。

  (6)詞法分析器(Lexer)類

  詞法分析器類標識文字使用的語言,還確定在文字中如何標識標記。預設的詞法分析器是英語或其他西歐語言,用空格、標準標點和非字母數字字元標識標記,同時禁用大小寫。包含8個基本物件:BASIC_LEXER、CHINESE_LEXER、CHINESE_VGRAM_LEXER、JAPANESE_LEXER、JAPANESE_VGRAM_LEXER、KOREAN_LEXER、KOREAN__MORPH_ LEXER、MULTI_LEXER。

  (7)過濾器(Filter)類

  過濾器確定如何過濾文字以建立索引。可以使用過濾器對文書處理器處理的文件、格式化的文件、純文字和 HTML 文件建立索引,包括5個基本物件:CHARSET_FILTER、INSO_FILTER INSO、NULL_FILTER、PROCEDURE_FILTER、USER_FILTER。

  (8)非索引字表(Stoplist)類

  非索引字表類是用以指定一組不編入索引的單詞 (稱為非索引字)。有兩個基本物件:BASIC_STOPLIST (一種語言中的所有非索引字) 、 MULTI_STOPLIST (包含多種語言中的非索引字的多語言非索引字表)。


 查詢

  建立了索引,就可以使用 SELECT 語句中的 CONTAINS 運算子發出文字查詢。使用 CONTAINS 可以進行兩種查詢:單詞查詢和ABOUT查詢。

  5.1 詞查詢示例

  詞查詢是對輸入到 CONTAINS 運算子中單引號間的精確單詞或短語的查詢。在以下示例中,我們將查詢文字列中包含 oracle 一詞的所有文件。每行的分值由使用標籤 1 的 SCORE 運算子選定:

SELECT SCORE(1) title from news WHERE CONTAINS(text, 'oracle', 1) > 0;

  在查詢表示式中,可以使用 AND 和 OR 等文字運算子來獲取不同結果。還可以將結構性謂詞新增到 WHERE 子句中。可以使用 count(*)、CTX_QUERY.COUNT_HITS 或 CTX_QUERY.EXPLAIN 來計算查詢的命中 (匹配) 數目。

  5.2 ABOUT查詢示例

  在所有語言中,ABOUT查詢增加了某查詢所返回的相關文件的數目。在英語中,ABOUT 查詢可以使用索引的主題片語件,該元件在預設情況下建立。這樣,運算子將根據查詢的概念返回文件,而不是僅依據所指定的精確單詞或短語。例如,以下查詢將查詢文字列中關於主題 politics 的所有文件,而不是僅包含 politics 一詞的文件:

SELECT SCORE(1) title from news WHERE CONTAINS(text, 'about(politics)', 1) > 0;


 索引維護

  索引建好後,如果表中的資料發生變化,比如增加或修改了記錄,怎麼辦?由於對錶所發生的任何DML語句,都不會自動修改索引,因此,必須定時同步(sync)和優化(optimize)索引,以正確反映資料的變化。
在索引建好後,可以在該使用者下查到Oracle自動產生了以下幾個表:(假設索引名為myindex):
DR$myindex$I,DR$myindex$K,DR$myindex$R,DR$myindex$N

  其中以I表最重要,可以查詢一下該表:

select token_text, token_count from DR$ myindex $I where rownum<=20;

  查詢結果在此省略。可以看到,該表中儲存的其實就是Oracle 分析你的文件後,生成的term記錄在這裡,包括term出現的位置、次數、hash值等。當文件的內容改變後,可以想見這個I表的內容也應該相應改變,才能保證Oracle在做全文檢索時正確檢索到內容(因為所謂全文檢索,其實核心就是查詢這個表)。那麼如何維護該表的內容,不能每次資料改變都重新建立索引,這就要用到sync 和 optimize了。

  同步(sync):將新的term 儲存到I表;

  優化(optimize):清除I表的垃圾,主要是將已經被刪除的term從I表刪除。

2例項

 環境配置
作業系統:Win2000 Sever+SP4
記憶體:256M
資料庫:Oracle9i Enterprise Edition Release 9.2.0.1.0+ ZHS16GBK(字符集)
第三方工具:PL/SQL Developer6.03

 步驟:
1. 要使用Oracle Text技術,當前資料庫中必須有CTXSYS使用者和CTXAPP角色。Orcale9i建立資料庫時,已經建立了CTXSYS和CTXAPP。
2. 建立測試使用者:
用system使用者登入。
SQL>create user wang identified by wang;
SQL>alter user wang default tablespace EXAMPLE;
SQL> grant connect,resource to wang;
SQL> grant ctxapp to wang;
SQL> alter user wang default role all;


3. 建立表:
用wang使用者登入。
SQL> create table mytest ( tid number primary key, fname varchar2(100), btext BLOB)

4. 錄入資料:
用system使用者登入
--建立目錄(資料庫伺服器)
SQL> create or replace directory BLOB_FILE_DIR as 'd:test';
SQL> grant read on directory BLOB_FILE_DIR to wang;
用wang使用者登入
--建立過程
CREATE OR REPLACE PROCEDURE insert_file (TID number,FILENAME VARCHAR2) IS
F_LOB BFILE;
B_LOB BLOB;
BEGIN
INSERT INTO MYTEST(tid,fname,btext)
VALUES (TID,FILENAME,EMPTY_BLOB ()) RETURN btext INTO B_LOB;
F_LOB:= BFILENAME ('BLOB_FILE_DIR', FILENAME);
DBMS_LOB.FILEOPEN (F_LOB, DBMS_LOB.FILE_READONLY);
DBMS_LOB.LOADFROMFILE (B_LOB,F_LOB,DBMS_LOB.GETLENGTH (F_LOB),1,1);
DBMS_LOB.FILECLOSE (F_LOB);
COMMIT;
END;

SQL> exec insert_file(1,'test.doc');


5. 設定索引參考項
SQL> begin
ctx_ddl.create_preference('cnlex','CHINESE_VGRAM_LEXER');
ctx_ddl.create_preference('mywordlist', 'BASIC_WORDLIST');
ctx_ddl.set_attribute('mywordlist','PREFIX_INDEX','TRUE');
ctx_ddl.set_attribute('mywordlist','PREFIX_MIN_LENGTH',1);
ctx_ddl.set_attribute('mywordlist','PREFIX_MAX_LENGTH', 5);
ctx_ddl.set_attribute('mywordlist','SUBSTRING_INDEX', 'YES');
end;
(如果資料庫的字符集是UTF8,建議使用CHINESE_LEXER詞法分析器)
--檢視自定義的參考項
SQL>select * from ctx_user_preferences;


6. 建立索引
SQL>create index idx_mytest on mytest(btext)
indextype is ctxsys.context
parameters ('DATASTORE CTXSYS.DIRECT_DATASTORE
FILTER CTXSYS.INSO_FILTER
LEXER WANG.CNLEX
WORDLIST WANG.MYWORDLIST');
(可以使用ctxcat索引型別,但好像不支援BLOB型)

--檢視
SQL>select * from dr$idx_mytest$I
SQL>select * from mytest where contains(btext,’任務’)>0

7. 刪除索引
SQL>drop index idx_mytest force;

8. 同步和優化
--同步
SQL>begin
Ctx_ddl.sync_index(‘idx_mytest’,’2M’);
End;



--優化
SQL>begin
Ctx_dll.optimize_index(‘myidx’,’full’);
End;

最好定期執行作業進行同步
create or replace procedure sync
is
begin
execute immediate
'alter index idx_mytest rebuild online' ||
' parameters ( ''sync'' )' ;
execute immediate
'alter index idx_mytest rebuild online' ||
' parameters ( ''optimize full maxtime unlimited'' )' ;
end sync;
/

Set ServerOutput on
declare
v_job number;
begin
Dbms_Job.Submit
(
job => v_job,
what => 'sync;',
next_date => sysdate, /* default */
interval => 'sysdate + 1/720' /* = 1 day / ( 24 hrs * 30 min) = 2 mins */
);
Dbms_Job.Run ( v_job );
Dbms_Output.Put_Line ( 'Submitted as job # ' || to_char ( v_job ) );
end;

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/756652/viewspace-242373/,如需轉載,請註明出處,否則將追究法律責任。

相關文章