如何為你的 App 加入搜尋:由簡單篩選到全文搜尋
要為你的 App 加入搜尋,先從最簡單又可行嘅方法開始:一個搜尋框呼叫伺服器路由,由伺服器將查詢與幾個欄位作比對,篩選資料庫嘅資料列,再加上分類或價格等篩選條件。當呢個方法未夠用,例如需要相關性排序、字詞詞幹處理,或者資料量好大,就改用資料庫嘅全文搜尋;只有當你需要強力嘅錯字容忍,或者喺非常大量嘅資料上即時顯示結果時,先考慮託管搜尋引擎。不論揀邊種,搜尋都必須尊重權限:用戶絕對唔應該搵到佢冇權睇嘅記錄。
「搜尋」對你嘅 App 代表咩
搜尋涵蓋幾種唔同嘢,而大部分 App 都需要多於一種:
- **關鍵字搜尋:**一個文字框,例如「搵提及『花園』嘅房源」。
- **篩選:**結構化選項,例如分類、城市、價格範圍、日期、狀態。
- **排序:**最新、最平、最相關。
- **自動完成:**打字時顯示建議。
- 錯字容忍:「restuarant」仍然可以搵到「restaurant」。
對於目錄、招聘板或商店,篩選通常比文字框更重要。揀工具之前,先決定你真正需要邊啲功能。
你嘅選擇
| 做法 | 運作方式 | 適合 | 限制 |
|---|---|---|---|
| 喺瀏覽器篩選 | 載入清單,然後用 JavaScript 篩選 | 細小嘅公開清單(幾百項以內) | 每位訪客都會收到全部資料;清單大時會慢 |
| 資料庫模式比對 | 伺服器查詢,例如「名稱包含該文字」,大小寫不敏感 | 小至中型 App、管理工具 | 無排序;大型資料表可能會慢;無詞幹處理 |
| 資料庫全文搜尋 | Postgres 為字詞建立索引,並為比對結果排序 | 大部分內容密集嘅 App | 除非加入模糊比對,否則對錯字應對一般 |
| 模糊比對(trigram) | Postgres 比較字元序列嘅相似度 | 名稱、短欄位,需要錯字容忍 | 需要擴充功能同索引;要調校 |
| 託管搜尋引擎 | 獨立服務為你嘅資料建立索引(Algolia、Meilisearch、Typesense、Elasticsearch 等) | 大型目錄、即時搜尋、需要強力錯字容忍 | 另一個要同步、付費同保護嘅服務 |
如果你嘅資料已經喺 Postgres 入面,佢內置嘅全文搜尋係一個很好嘅中間選擇。佢會將文字拆成字詞、還原為詞幹(令「running」可以搵到「run」)、忽略常見字,並按比對程度排序結果。只要有合適嘅索引,喺大型資料表上仍然會好快。
提示詞例子
簡單開始:
喺房源列表頁加入搜尋框同篩選。搜尋應該以大小寫不敏感嘅方式,將查詢與標題及描述作比對。篩選條件:分類(下拉選單)、城市(下拉選單)同最高價格。搜尋喺伺服器上以分頁 API 路由進行,每頁 20 項結果。將搜尋同篩選條件保留喺網址中,令結果可以分享,而返回按鈕亦可以運作。冇符合結果時顯示友善嘅空白狀態。
升級到全文搜尋:
將房源搜尋改用 Postgres 全文搜尋,標題(權重較高)同描述都納入。加入正確嘅索引,按相關性排序結果,並保留現有篩選同分頁。唔好改動任何現有資料。
為名稱加入錯字容忍:
為商戶名稱加入模糊比對,令細小嘅錯字都仍然可以搵到結果。如果可用,使用 trigram 相似度,並加入索引;如果唔可以用,就退回現有嘅搜尋方法。
逐步做法
- **列出人哋會搜尋乜嘢。**要搜尋邊啲欄位(標題、描述、標籤、名稱)?有邊啲篩選?如果可以,問吓幾位真實用戶。
- **從伺服器端開始。**新增一個 API 路由,接收查詢同篩選條件,並只回傳一頁結果。唔好將所有資料載入瀏覽器。
- **喺查詢中套用權限。**如果用戶只能睇自己嘅記錄,或者只能睇已發布嘅記錄,呢個條件應該同搜尋放喺同一個查詢入面。
- 由第一天就加入分頁,可以用頁碼,或者「載入更多」。
- 將搜尋狀態放入網址(例如
?q=garden&city=leeds)。咁樣連結可以分享,返回按鈕亦會正常運作,而如果你希望搜尋引擎爬取經篩選嘅頁面,佢亦可以爬取。 - **打字即搜尋要加入防抖(debounce)。**停止打字幾百毫秒後才發出查詢,唔好每按一下鍵就發一次請求。
- 當你知道會篩選同搜尋邊啲欄位之後,就加入索引。
- 升級:先全文搜尋,再模糊比對,最後先考慮託管搜尋引擎;只有當較簡單嘅方法無法滿足真實用戶需要時,才升級。
- 用接近真實嘅資料測試:幾百或幾千筆資料列、特殊字元、空白查詢、超長查詢,如果你支援其他語言,亦要測試其他語言。
常見錯誤
- **將整個資料表載入瀏覽器。**50 項時無問題,但 50,000 項就會好慢,而且會暴露每一筆記錄,包括用戶冇權睇嘅記錄。
- **忽略權限嘅搜尋。**搜尋係常見嘅洩漏點:私人或草稿記錄會出現喺結果中,因為搜尋查詢漏咗「只限自己」或「只限已發布」嘅條件。
- **用原始用戶輸入組成 SQL。**一定要用參數化查詢。AI 生成工具通常會這樣做,但你見到字串被直接黏合時,要留意。
- 冇空白狀態。「冇結果」如果附上建議(清除篩選、檢查拼寫),可以避免用戶離開。
- **冇索引。**用測試資料時搜尋感覺良好,但真實資料增長後就會變慢。
- **一開始就跳去用搜尋服務。**之後你就要保留另一份資料副本並同步、處理刪除,亦要保護另一組金鑰,而往往冇帶來任何可見嘅好處。
- **忘記手機版。**篩選需要適合手機;篩選抽屜或可摺疊面板,通常比側邊欄更好用。
檢查清單
- 你知道搜尋哪些欄位,以及有哪些篩選
- 搜尋喺伺服器上執行,並回傳分頁結果
- 查詢套用與 App 其他部分相同嘅權限
- 用戶輸入以參數傳遞,絕對唔會黏合到 SQL 入面
- 搜尋狀態保留喺網址中
- 打字時有防抖處理
- 被搜尋同篩選嘅欄位已建立索引
- 空白、冇結果同錯誤狀態都清楚易明
- 已用接近真實嘅資料量同混亂輸入測試
喺 Mythex 加入搜尋
喺以 Mythex 建立嘅 App 中,資料通常存放於專案自己嘅 Postgres 資料庫,所以你可以由上面嘅提示詞開始:先用模式比對,當需要排序時再加入 Postgres 全文搜尋。如果你想用託管搜尋引擎,請使用你自己嘅帳戶同金鑰,將金鑰儲存為專案機密,然後要求 Agent 喺伺服器端建立索引並查詢,做法見整合任何 API。
搜尋係好多 App 嘅核心:要了解佢點樣融入產品其他部分,可以參閱如何建立目錄網站、如何建立招聘板同如何建立市集。
常見問題
為 App 加入搜尋最簡單嘅方法係咩?
如果你嘅資料存放喺資料庫,最簡單係用一個伺服器路由,對幾個欄位做大小寫不敏感嘅比對,篩選資料列。如果係一個已經載入瀏覽器嘅小型清單,喺瀏覽器內篩選就更加簡單。
搜尋一定要用 Algolia 或 Elasticsearch 嗎?
一開始通常唔需要。Postgres 全文搜尋已經可以好好處理字詞比對、排序,以及數千至數百萬筆資料列。只有當你需要強力嘅錯字容忍、喺大量資料中打字時即時顯示結果,或者進階嘅相關性調校,先至值得使用託管搜尋引擎。
點解我嘅搜尋搵唔到打錯字嘅結果?
基本比對同標準全文搜尋,都係按輸入嘅字詞(或其詞根)去搵,所以拼錯字就會搵唔到。你需要模糊比對,例如 Postgres 嘅 trigram 相似度,或者具備錯字容忍功能嘅搜尋引擎。
搜尋應該喺瀏覽器執行,定係喺伺服器執行?
除咗細小嘅公開清單之外,都應該喺伺服器執行。伺服器端搜尋可以擴展、尊重權限,亦唔會將整個資料集傳送俾每位訪客。