核心原則

搜尋引擎的「匹配模式」是個經常被忽略的維度 — 工具的預設行為跟使用者的 mental model 不對齊時、產生 silent 失敗:使用者打字、看不到預期結果、誤以為「沒有」、不會 report bug。

匹配模式例:query「pre」會匹配典型來源
Exactpre(不含「pre」這個 token)DB = 比較
PrefixpreprefixprefetchpresencePagefind / Lunr 預設
Substring上面 + backpressureSuperPressDB LIKE '%pre%'
Fuzzy上面 + prvpre1(編輯距離)Algolia、TypeSense
Semantic上面 + beforeprior(語意相近)Vector search / LLM

使用者被 Google / 桌面搜尋訓練、預期 substring 或更高層級。預設拿到 prefix 的 site search → 「pre」找不到 backpressure → 看起來像 bug 但其實是 capability 落差。


為什麼預設是 prefix

Static site search engines(Pagefind / Lunr / MiniSearch 預設)選 prefix matching 的原因:

因素PrefixSubstring
Index sizeO(N)O(N²)(要 index 所有後綴)
Query speed快(trie)慢(全掃 substring)
跨語言支援容易中文 / CJK 邊界不明確
Build time

對 static site(沒 server)、index 是要下載到 client 的 — substring index 可能 5-10x 大、unacceptable。Pagefind / Lunr 選 prefix 是「對齊 size constraint」、不是「對齊使用者意圖」。

這是個典型的 #67 寫作便利度跟意圖對齊反相關 — 工具預設是「實作便利位置」、不是「使用者意圖位置」。


為什麼這個 gap 是 silent

#55 Filter × Source 層錯位 共用結構:使用者打字看到結果列表、結果不空、看起來「有東西」、不會懷疑 engine 沒在做完整 search。

silent 失敗的條件:

  1. Prefix matching 對某些 query 仍能回到結果(排版上看起來「有用」)
  2. 使用者不知道「沒看到的還有什麼」
  3. 只有當 query 剛好不是任何 token 的 prefix、才會 0 結果(極少見、這時才會懷疑)

對照 #55 silent 失敗條件 三條件 — 完全一樣的結構:「有部分結果掩蓋了缺口」。


多面向:跨工具的匹配模式對照

工具預設匹配模式可調整為
Pagefind v1.5Word-prefixExact only(useExact
LunrStem + prefixWildcard(q+'*'
MiniSearchPrefixSubstring(prefix: false, fuzzy: 0.2
FlexSearchToken-based多種 tokenizer(含 ngram)
Fuse.jsFuzzy可關掉 fuzzy 變 substring

Backend / DB

工具匹配模式
SQL =Exact
SQL LIKE '%X%'Substring(O(n) scan)
SQL FULLTEXTToken + stem + (有時 prefix)
ElasticSearch配置:term / match / wildcard / fuzzy / regexp
PostgreSQL trigramSubstring + similarity
Vector DB(Pinecone 等)Semantic

命令列 / IDE 搜尋

工具預設
grepSubstring(regex)
rgSubstring(smart-case + regex)
Vim /Regex
VSCode 搜尋Substring(含 fuzzy file search)

共通結構:每個工具預設不同、使用者帶著舊工具的 expectation 來、不對齊時 silent 失敗。


識別三問

寫之前 / debug 時、自問:

1. 這個工具的預設匹配模式是什麼?

讀 docs、不要假設。Pagefind docs 寫 “Pagefind matches by word prefix”。Lunr 文件寫 “Lunr does prefix matching by default”。 預設不是直覺。

2. 使用者預期哪種匹配模式?

使用者被別的工具訓練。使用者基數越大、越接近 Google substring + fuzzy 預期。

使用者類型預期匹配模式
一般使用者(被 Google 訓練)Substring + fuzzy + semantic
開發者(用 grep / IDE)Substring + regex
資料庫使用者(寫 SQL)看你給的 hint
命令列重度使用者預設 regex

3. Gap 多大?是否 silent?

工具預設 vs 使用者預期不一致時、評估「使用者會在多少 case 中遇到不一致」。

  • Prefix vs Substring:使用者只要打詞中間部分就 silent 失敗、頻率高
  • Prefix vs Fuzzy:使用者打錯字才會發現、頻率低
  • Substring vs Semantic:使用者用同義詞才會發現、頻率中

頻率高的 gap 必須有對策。


五種對策(跟 #59 Filter × Source 五策略 同構)

A:選用支援目標匹配模式的引擎

Pagefind 不支援 substring → 換 MiniSearch / FlexSearch。Lunr 不支援 fuzzy → 換 FlexSearch / Fuse.js。

  • 適合:早期決策、index size 不是 bottleneck、能接受工程量
  • 代價:換引擎成本(API 不同、index 重建、UI 重整合)

B:在 build time pre-tokenize、增加替代 token

在 build pipeline 拆字、把 backpressure 加進 search index 的多個 token:back + pressure + backpressure + back-pressure。Pagefind 透過 data-pagefind-meta 或多份 hidden text 注入。

  • 適合:少量已知關鍵詞 / 跨語言邊界(中文)/ 能控 build pipeline
  • 代價:手動標記、index 變大、新詞要加進清單

Pagefind 找不到時、fetch 一份頁面 metadata(title + slug)、做 client-side substring filter。

  • 適合:頁面數量 < 10000、可接受第二層延遲
  • 代價:需要額外 fetch + 客戶端 substring scan、兩種 result UI 整合

D:UX hint 明示匹配模式

把限制告訴使用者:「搜尋為前綴匹配、想找 X 請打 Y」。對應 #66 明示語意縮小

  • 適合:成本最低、只需文字 hint
  • 代價:使用者要學新規則、不對齊 Google expectation

E:接受限制(不告知)

不做任何處理、silent 接受。這是反模式(同 #55 silent 失敗)— 使用者誤以為「沒有相關內容」、放棄。


跟其他抽象層原則的關係

原則跟本卡的關係
#55 Filter × Source 層錯位都是「使用者意圖跟工具實際行為的 silent gap」、本卡是 matching 維度的展現
#63 資料源的形狀形狀是 source 的 capability 維度、本卡是「matching mode」這個 capability 維度
#67 寫作便利度跟意圖對齊反相關工具預設是實作便利、使用者預期是 mental model 對齊、反相關
#68 驗收的時間軸 Checkpoint 1「source capabilities 是否對齊使用者預期」屬意圖完整集 — 容易跳過
#72 高 ROI 無外部觸發「讀 search engine docs 確認 matching mode」沒便利路徑、容易跳過

對應的實作篇

  • 本 blog 搜尋頁的 Pagefind prefix-match 限制(這次 user 報的 case)
  • 任何用 client-side search 的 SPA / 靜態站
  • 內部 admin tool 的 search box(往往用 SQL LIKE 的 substring、跟使用者 Google 預期反方向)
  • ElasticSearch 配置時 term vs match query 的選擇

判讀徵兆

訊號該做的事
寫 search feature、沒讀工具的 matching mode docs跑識別三問、確認預設
使用者報「我搜 X 找不到、但是有 X」多半是 matching mode gap、不是 bug
使用者打字、結果列表 0 筆、但確實有相關內容不對齊的訊號明顯、需要對策
Search 跨多種使用者(Google trained / dev / DB user)Mental model 異質、選擇性高(A/B + C 組合通常需要)
工具 docs 寫「matches by word prefix」這類字眼警訊 — 預設不是 substring
Pagefind / Lunr / 任何 static site search預設 prefix、要主動評估是否符合需求

核心原則:搜尋引擎的匹配模式是個容易被忽略的 capability 維度。工具預設多半是 prefix(為了 index size)、使用者預期多半是 substring 或更高(被 Google 訓練)。沒對齊 = silent 失敗:使用者誤以為內容不存在、不會 report bug。Checkpoint 1 列「使用者意圖完整集」要包含「使用者打字行為的預期」。