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

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

調研方案範圍
調研目的在於找到一個在功能和性能上都比較優秀的全文檢索的知識庫系統實現方案;在調研過程中優先考慮如何實現全文本檢索功能,結合考慮系統的功能、性能、以及構建完整系統的效率。
構建全文檢索的知識庫系統有多種行之有效的方案,主要有以下三種實現思路:
方案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中也能夠使用。
(未完,待續)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章