Xapian 是一款開源的C++信息檢索系統,內部系統試用了xunsearch,所以稍微瞭解了一下「蝦片」的機制 html
先看一下執行過程: 數據庫
檢索相關:
Xapian::Database 用於讀取索引。
Xapian::Enquire 提供檢索服務,與Xapian::Database配合使用
Xapian::QueryParser 查詢語句解析器
Xapian::Query 查詢語句
Xapian::MSet 檢索返回的匹配結果記錄集
建索引相關:
Xapian::WritableDatabase 用於創建索引。
Xapian::TermGenerator 很是簡單的切詞、建索引器,不是必須使用的,可用其餘替代,可是提供了一些幫助函數,很是好用。
共用:
Xapian::Document 文檔的抽象。
Xapian::SimpleStopper 停用詞
Xapian::Error 異常類,.get_description()獲取詳細信息。
後端相關:
Xapian::Database::Internal 每一個後端都要實現
Database,也能夠稱爲Index
Database類型
- auto
-
- brass
- 當前開發中的後端,並將做爲1.4.x版本起的默認後端
- chert
- 1.2.x的默認後端,支持增量修改、單寫者+多讀者的併發。
- 高效且可擴展
- flint
- 1.0.x的默認後端,類chert
- inmemory
- 全內存的database,可用於創建臨時小database
- quartz
- 1.0的默認後端,1.1.0後移除
文檔
- 粒度
- RMDB:表中的一條記錄
- html:一個html文件/一個標籤
- 表示方式
- 32位 Document ID
- 3個組分
- 數據data
- 只存儲,不分析其內容,一般用於結果的返回
- 是文檔的部分/所有數據
- 詞集terms
- 基本的查詢單元
- 值域集values
分詞器
- xapian沒有Field的概念,經過在每一個詞前加前綴來標識
-
須要注意的是,在Xapian中,若是你在索引的時候使用了TermGenerate來進行分詞,那在查詢的時候必定要使用QueryParser來對查詢條件進行解析
索引
一些限制:
- Term Length:一個詞限制在256個字節內,
- Document Data:一個data區不能大於100MB,默認是8KB
- Document value:和一個data區的限制是同樣的,但通常建議value不要太大
- Document ID: 當前範圍是32bit,大概在43億左右,文檔刪除的ID號不會被從新利用,除非你對數據庫進行compact
- B-tree block number: 目前支持最大爲32bit個塊
- OS file size:全部操做系統對於單個文檔的限制對於Xapian都適用,如ext4對於單個文件的大小爲16TB,
- Document length:文檔長度的存儲限制爲unsigned 64bit
索引格式
- Xapian有多種數據庫格式
分面搜索(faceted search)
- 將搜索結果進行聚類處理
並行讀寫操做
- 寫
-
數據庫只支持單個數據庫寫對象存在
-
也就是說在建立一個DataBaseWritable對象的時候,會對數據庫進行加鎖,若是另外一個寫數據庫對象再去寫這個數據庫時,會出現DatabaseLockError錯誤。
- 讀
-
可是多個讀對象是同時存在於同一個數據庫。
- 更新
-
讀/寫操做隔離
-
當打開一個數據庫準備進行讀操做時,會建立一個找開數據庫的鏡像,這樣有寫操做時,讀對象是不可見的,除非讀對象運行reopen()操做。
- 限制
-
如今的Xapian多版本同步仍是有一些限制的,特別是當數據庫有兩個版本同時存在時,也就是說有多個讀,一個寫數據庫操做時,當寫數據庫只修改了數據庫,運行了一次commit時,是沒問題的,可是當寫數據庫又運行了第二次commit時,讀數據庫操做會收到了一個Xapian::DatabaseModifiedError,在這種狀況下,讀數據庫操做要更新其數據庫的鏡像版本,使用reopen()操做,這個要在編程上注意一下。
數據同步
- 同時支持數據庫的複製,並且只複製那些變動過的索引數據,這樣可使用數據冗餘,達到負載均衡的目的
常見問題
- DatabaseLockError錯誤
- 數據庫只支持單個數據庫寫對象存在,也就是說在建立一個DataBaseWritable對象的時候,會對數據庫進行加鎖,若是另外一個寫數據庫對象再去寫這個數據庫時,會出現DatabaseLockError錯誤
- 可是多個讀對象是同時存在於同一個數據庫。
- DatabaseModifiedError錯誤
- 當打開一個數據庫準備進行讀操做時,會建立一個找開數據庫的鏡像,這樣有寫操做時,讀對象是不可見的,除非讀對象運行reopen()操做。這樣讀/寫操做就隔離了。
- 如今的Xapian多版本同步仍是有一些限制的,特別是當數據庫有兩個版本同時存在時,也就是說有多個讀,一個寫數據庫操做時,當寫數據庫只修改了數據庫,運行了一次commit時,是沒問題的,
- 可是當寫數據庫又運行了第二次commit時,讀數據庫操做會收到了一個Xapian::DatabaseModifiedError,在這種狀況下,讀數據庫操做要更新其數據庫的鏡像版本,使用reopen()操做。
- 多線程支持
- Xapian沒有顯示的支持多線程,爲了不沒必要要的線程死鎖,Xapian沒有使用任何全局變量,因此你能夠你的多線程應用中放心的使用Xapain對象。
- 可是一些Xapian對象內部是有關聯的,如Xapian::Database::get_document(),返回的對象Xapian::Document對象內部保存了一個指向DataBase的一個引用,因此它不適合在多線程中使用,因此在多線程中使用Xapian的時候仍是要注意一些東西的。