用程式管理全文索引:CreateFTIndex、UpdateFTIndex,與本機 vs 伺服器的分界
全文索引是讓 FTSearch 又快又強的來源 —— 它不只讓查詢變快,還開啟了萬用字元、AND/OR/NEAR 這類運算子、以及依相關性排序(FTSearchScore)這些一般公式掃描做不到的能力。少了它,FTSearch 不會自動退成 db.Search(那是另一個以公式選取、逐份文件求值的方法):在本機資料庫,FTSearch 照樣能查,只是退化成慢的即時掃描並失去相關性排序;在伺服器資料庫,沒索引的全文查詢通常直接拋出「資料庫沒有全文索引」的錯(就是你在 XPages view 搜尋沒索引時會看到的那則訊息),除非設了 TEMP_INDEX_MAX_DOC 之類的 ini。所以自然會想用程式建立與維護那個索引。NotesDatabase 讓你做:CreateFTIndex、UpdateFTIndex、RemoveFTIndex、IsFTIndexed。絆倒人的不是 API — 是一個本機 vs 伺服器的分界,直到你的程式對著伺服器資料庫悄悄什麼都沒做(或拋錯)才會發現。
重點摘要
- 用
db.IsFTIndexed把關 —「指出一個資料庫是否有全文索引」(資料庫必須開啟)。 db.CreateFTIndex(options&, recreate)建立索引。recreate=True刪除並重建;recreate=False在已有索引時什麼都不做。只限本機資料庫。db.UpdateFTIndex(createFlag)增量刷新既有索引;createFlag=True在沒有時建立(需要至少一份文件)。也只限本機。- 分界: 那些管理方法只限本機,但
FTIndexFrequency(自動更新頻率)只限伺服器。伺服器資料庫的索引由 Updall 工作建立/重建,不是這些方法。 options&是一個 bitmask:FTINDEX_ATTACHED_FILES(1)、FTINDEX_ENCRYPTED_FIELDS(2)、FTINDEX_ALL_BREAKS(4)、FTINDEX_CASE_SENSITIVE(8)、FTINDEX_ATTACHED_BIN_FILES(16)。相加來組合。
檢查、建立、更新
正統寫法是依 IsFTIndexed 分支,然後 create(重建)或 update:
Sub Initialize Dim session As New NotesSession Dim db As NotesDatabase Set db = session.CurrentDatabase
' 管理方法只對「本機」資料庫有效。 Dim options As Long options = FTINDEX_ALL_BREAKS + FTINDEX_ATTACHED_FILES ' 索引斷句 + 附件文字
If db.IsFTIndexed Then Call db.UpdateFTIndex(False) ' 增量刷新既有索引 Print "Existing FT index updated" Else Call db.CreateFTIndex(options, False) ' 用選定的 options 建立 Print "New FT index created" End IfEnd Suboptions bitmask 控制什麼被索引:附件文字(FTINDEX_ATTACHED_FILES)與二進位附件內容(FTINDEX_ATTACHED_BIN_FILES)最會撐大索引;FTINDEX_ALL_BREAKS 記錄句/段落斷點、讓 PARAGRAPH/SENTENCE 查詢運算子能用;FTINDEX_CASE_SENSITIVE 啟用 EXACTCASE。recreate 與 createFlag 這一對要分清楚:
CreateFTIndex(options, True)— 用那些 options 刪除並完整重建。別排程跑它;它每次都把索引丟掉。CreateFTIndex(options, False)—「如果這個參數為 False 且索引存在,不採取任何動作」。UpdateFTIndex(True)— 沒有就建、有就刷新。這是「確保它存在且是最新」的呼叫。(空資料庫即使傳True也不會有索引 — 它需要至少一份文件。)UpdateFTIndex(False)— 只刷新;沒索引就 no-op。
RemoveFTIndex 刪除索引(只限本機,而且是 no-op — 沒索引也不會錯)。
沒人料到的分界
這是文件講得很白、但開發者一直漏掉的部分。管理方法說,原文:「這個方法只對本機資料庫有效。」UpdateFTIndex 的說法是「如果你試圖在一個非本機的資料庫上建立全文索引,Notes 會回傳錯誤」。所以對著一個在伺服器上的資料庫,CreateFTIndex / UpdateFTIndex / RemoveFTIndex 不會悄悄運作 — 它們拋錯。
而唯一是伺服器範圍的屬性正好相反:FTIndexFrequency(自動更新頻率 —FTINDEX_DAILY、FTINDEX_SCHEDULED、FTINDEX_HOURLY、FTINDEX_IMMEDIATE)「只適用於伺服器上的資料庫」。所以你能用程式設定一個伺服器索引多久刷新一次,卻不能用程式建立那個伺服器索引。
那伺服器索引誰建? Updall 伺服器工作。管理員跑 load updall <database> 更新 view 與全文索引,load updall <database> -X — 注意大寫的 -X — 來重建損毀的全文索引。這裡要精確:-X 是重建、不是建立初始索引。伺服器資料庫的初始全文索引,是透過 Domino Administrator(資料庫屬性 / Full Text)設定、或啟用索引後讓 Update/Updall 建起來。LotusScript 方法就是沒辦法伸手到伺服器資料庫。
實務指引
- agent 建立並搜尋的本機暫存/臨時資料庫:放心用
CreateFTIndex/UpdateFTIndex— 那正是它們的範圍。 - 伺服器正式資料庫:別想用 LotusScript 索引它們;那是管理員/Updall 的地盤。從程式你能讀
IsFTIndexed來檢查、設FTIndexFrequency來調頻率,但建立本身在伺服器端。 - 永遠用
IsFTIndexed把關FTSearch。沒索引時,由你的程式決定路徑 —— 先建/刷新索引,或改用公式版的db.Search(O(N) 掃描)當明確的替代路徑 —— 而不是假設FTSearch會自己降級。尤其在伺服器資料庫上,沒索引的全文查詢會直接拋錯,不會默默慢慢跑。
同類別在其他語言
| LotusScript | Java | SSJS / XPages |
|---|---|---|
db.CreateFTIndex(opts, recreate) | db.createFTIndex(opts, recreate) | database.createFTIndex(...) |
db.UpdateFTIndex(create) | db.updateFTIndex(create) | database.updateFTIndex(...) |
db.IsFTIndexed / FTIndexFrequency | db.isFTIndexed() / getFTIndexFrequency() | database.isFTIndexed() / … |
Java 與 SSJS 的 Database 類別一個方法對一個方法地對應,而同樣的本機 vs 伺服器分界在每個語言都適用 — 它是索引實體住在哪裡的性質,不是你從哪個 API 面呼叫它的性質。