1. 程式人生 > >全文檢索知識庫系統方案 (一)

全文檢索知識庫系統方案 (一)

題記:前段時間做了一個全文檢索的知識庫系統構建方案的調研,在此分享。

調研方案範圍 調研目的在於找到一個在功能和效能上都比較優秀的全文檢索的知識庫系統實現方案;在調研過程中優先考慮如何實現全文字檢索功能,結合考慮系統的功能、效能、以及構建完整系統的效率。 構建全文檢索的知識庫系統有多種行之有效的方案,主要有以下三種實現思路: 方案A 使用支援全文檢索功能的資料庫,構建大型文字管理資料庫系統,從檔案管理資料庫出發設計知識庫系統; 方案B 使用全文搜尋引擎實現全文字檢索功能,以此開始設計知識庫系統; 方案C 使用WIKI構建知識庫系統。 以下分別介紹。 1 全文檢索資料庫方案 支援全文檢索的資料庫以建立和維護索引的方式對儲存在資料庫表中的大型文本系統執行有效率的文字搜尋。 知識庫系統中全文搜尋的物件主要是表達知識資訊的文章,典型的搜尋應用可能是查找出標題或者內容中含有某個搜尋項的所有文章。把知識庫中的文章儲存在按照標題、內容等文字欄位建立起來的資料庫表中,實現知識庫系統中的全文查詢也就同資料庫中的全文檢索功能等同起來了。 Oracle實現全文檢索的的元件在Oracle9i中稱為Oracle Text。Oracle Text的體系結構如下圖, 在本次調研所關注的範圍裡,這個體系結構的中心是為儲存在資料庫中的文章的標題、內容等欄位資訊建立索引。

 圖一 Oracle Text體系結構  1.2 DEMO - 使用Oracle資料庫實現中文全文檢索 目標:確認Oracle Text支援中文全文檢索功能、總結操作過程,並探求更好的效能。(demo基於Oracle9.02個人版,企業版和標準版應該得到同樣的結果。) 這裡介紹主要的過程: 步驟1 確保資料庫的一些配置項 (1)檢查資料庫是否安裝了Oracle Text元件(Oracle9i預設安裝) 檢查資料庫是否具有CTXSYS使用者和CTXAPP角色; 如果沒有則執行$ORACLE_HOME/bin/dbassist, 選擇'modify database', 然後在選擇資料庫功能時將jserver和intermedia都選中; (2) 檢查伺服器是否有對PLSExtProc服務的監聽 Windows Shell命令視窗下執行lsnrctl status,在列印資訊中通常有 PLSExtProc has 1 service handler(s) 這樣一段即表明外部呼叫功能開啟; 否則需要修改$ORACLE_HOME/network/admin/listener.ora以開啟該功能; 步驟2 建立資料庫knowledge並建立一個ctxtest使用者
(1)建立資料庫knowledge (2)在資料庫knowledge下建立ctxtest使用者 CREATE USER ctxtest IDENTIFIED BY ctxtest; (3)賦予ctxtest使用者connect、ctxapp、resource角色 GRANT CONNECT, CTXAPP, RESOURCE TO ctxtest;  步驟3 進行資料庫設計並建表 (1)使用PowerDesigner為知識庫系統建立一個大致的概念模型如下,匯出物理檢視並生成SQL指令碼,在資料庫例項knowledge中生成表;demo中需要用到Article和Version兩張表,這兩張表分別表示文章的和文章的每個版本,並且假定每個版本的內容、作者、附件都可以改變,但是文章標題不可以修改。

圖二 知識庫系統的概念模型

(2)在建立的表中插入一些記錄,其中包含一條: insert into version(id, content) values(1,'上午好'); insert into version(id, content) values(2,'<title>上午好</title>'); insert into version (id, content) values(3,'我是中國人,我深深的愛著我的祖國和人民,我是人民的兒子'); 步驟4 建立索引 以ctxtest使用者連線到knowledge資料庫 (1)建立首選項 begin tx_ddl.create_preference('my_lexer','chinese_vgram_lexer'); end; (2)建立索引 create index myindex on version(content) indextype is ctxsys.context
parameters('lexer my_lexer'); 如上命令以Oracle提供的中文分詞器chinese_vgram_lexer對version表的content欄位建立了索引。建立的索引儲存在CTXSYS使用者預設的臨時表空間裡以dr$打頭的4個表: dr$myindex$i、dr$myindex$k、dr$myindex$r、dr$myindex$n,其中以表dr$myindex$i最為重要。查詢一下該表 select token_text, token_count from dr$myindex$i; 可以發現該表中儲存的就是對article表的content欄位分析得到的全部索引項。 步驟5 執行查詢 Select * from version where contains(content,’中國人’) >0; 可以查出剛剛插入表格中的第三條記錄 步驟6 建立維護索引的JOB 索引在剛才執行建立索引的語句後被建立,但是此後對資料庫執行的任何增刪改操作都不會引起索引的同步更新。因此需要建立一個同步更新操作的JOB執行同步更新操作; 另一方面,在執行多次同步更新之後,索引區會引起索引項的稀釋,勢必需要優化,因此還需要為資料庫建立一個定期優化索引結構的JOB. 這兩個job可以建立如下: 同步sync:
VARIABLE jobno number;
BEGIN  DBMS_JOB.SUBMIT(:jobno,'ctx_ddl.sync_index(''myindex'');', SYSDATE, 'SYSDATE + (1/24/4)');
commit; END; 優化optimizer:
VARIABLE jobno number;
BEGIN DBMS_JOB.SUBMIT(:jobno,'ctx_ddl.optimize_index(''myindex'',''FULL'');', SYSDATE, 'SYSDATE + 1');
commit; END; 其中, 第一個job的SYSDATE + (1/24/4)是指每隔15分鐘同步一次,第二個job的SYSDATE + 1是每隔1天做一次全優化。具體的時間間隔,可以應用需要而定。 至此,全文檢索功能已設定完成。 1.3 兩個問題 1.3.1 Oracle Text 對HTML建立索引的支援 知識庫系統一般採用線上編輯器編輯文章,所見即所得的文字一般採用html語法。而html原始檔中大量的標記符號不應該參與與查詢字串的匹配,因為不僅這些如<title>這樣的格式標記在搜尋如“title”時不應該被搜尋到、而且如果不加過濾的對這些部分建立索引項勢,對於一個大型的文字查詢系統而言會極大的影響效率。 回顧Oracle Text的體系結構圖,Oracle Text在將文字分詞建立索引項時已經充分考慮到了支援html、xml等格式化的文件在建立索引時過濾掉無表意內容的格式指令碼。  這可以通過在建立索引時設定Section Groups區分組來實現。SQL語句如下: BEGIN    ctx_ddl.create_section_group ('my_section_group', 'BASIC_SECTION_GROUP');    ctx_ddl.add_field_section (       group_name=> 'my_section_group',       section_name=> 'Title',       tag   => 'title',       visible=> FALSE    ); END;/
DROP INDEX my_html_idx; CREATE INDEX my_html_idx ON version( context ) INDEXTYPE IS ctxsys.CONTEXT PARAMETERS( 'section group my_section_group' )/
SELECT id  from version WHERE contains (content, '上午好 within title') > 0; 1.3.2 中文分詞程式設定的改進 在為建立引擎建立lexer首選項時,設定的分詞器是Oracle提供的chinese_vgram_lexer。實際上Oracle還提供了一個chinese_lexer. 比較而言,這個分詞器分詞演算法更智慧、效率更高。在demo中就表中第三條記錄的content欄位建立索引項時,索引項由chinese_vgram_lxer的53個減少到31個。 在官方文件中提到chinese_lexer僅支援UTF-8字符集的資料庫,demo過程中,發現在zhs16gbk中也能夠使用。 (未完,待續)