ElasticSearch 打造搜尋產品的經驗談
目錄
這是以公司要為產品打造搜尋功能,甚至把搜尋當產品的角度,在不同的層級需要注意的大略事項與指南,共分四部分:產品地位、生態系、metrics 衡量、以及 ES 工程
Disclaimer: 不同領域、資料、使用情境,打造搜尋的方式也不一樣。這是以我幾年在電商與垂直搜尋的個人經驗,一定有很多沒有考慮到的
搜尋是否為賣點? #
搜尋可大可小,公司要先問自己:為什麼要做搜尋?
- 搜尋是否為產品重要流量入口?或是想投資變成重要入口?
- 可大可小:可以是數十人投資一兩年,也可以是兩三人投資三個月。哪些搜尋 feature 是核心?哪些是加分?
- 站在公司的立場,自己從無到有開發維護搜尋?還是用別人的服務?機會成本:同樣資源投資在其他地方有沒有可能比較好?
- 搜尋體驗:precision or recall? 給使用者答案或探索(推薦)?搜尋結果希望「寧缺勿濫」或「寧爛勿缺」?
打造搜尋生態系 #
- Corpus data pipeline: 要索引的資料的來源?(自產、客戶、User generated, …)有固定規格嗎?大小頻率?需要清洗嗎?等等等
- 搜集互動資料(e.g. 搜尋了什麼,點了什麼),了解 query 的分佈,跟目前使用者滿意度
- 衡量系統:
- 能方便執行「人工單點審查」以及「大資料評比」,評估搜尋品質
- 自動線下測試(e.g. 固定測資,一鍵 / CICD 測量?)
- 產品線上品質(e.g. 點擊率)
- 搜尋模型/公式更新?
- 需要衡量系統
- 公式/模型本身要有參數可以變化調整
- 更新的一種最笨方法:暴力測試不同參數組合,以衡量系統出來的分數,取最高分的那組參數
- 「後門」系統
- 不完全遵照 elasticsearch 結果,甚至有可能直接蓋過
- 可以為獨立系統,也可以整合在「產生 ES query」裡
- 應付流行詞,如果怎麼調整公式,但搜尋結果就是爛
- 應付老闆 (huh?)
- 飲鴆止渴:維護答案有成本
- UIUX (e.g. auto complete, related search, …), 搜尋結果回傳速度 (FE, API, BE/index) 等等
搜尋評量 metrics #
- 概念:搜尋結果有絕對單一個答案嗎?還是多個模糊建議都適合給使用者?這走向會決定哪類型的衡量比較好
- 概念:搜尋品質並非說一是一的程式,很容易「修東壞西」,所以要有測試資料。
- 概念:做好了就算不動他,品質也可能會爛,因為使用者的 query 分布變化,資料變化 (input drift, data drift)
- 測試資料收集:
- 使用者 log(e.g. 哪個關鍵字較流行)
- 商業策略(e.g. 跟哪家公司關係利益較大,整體產品策略,使用者習慣養成等等)
- 要評量搜尋品質,盡量用大量資料,且能反應使用者習慣,或能反應商業策略
- 使用者習慣如果需要培養(例如教育使用者要怎麼用你們的搜尋),一味取用目前使用者 log 不一定好
- recall 跟 ranking 是搜尋兩階段
- recall: 有多少該出的是真的出了
- precision: 出的裡面有多少是該出的
- ranking: 該出的結果是否排在上面容易看見
- 做到極致的時候會需要 tradeoff:產品需要決定是寧缺勿濫 (precision) 還是寧爛勿缺 (recall)
- Google “ranking metrics” 了解有哪些指標
- 這篇應該不錯 https://towardsdatascience.com/comprehensive-guide-to-ranking-evaluation-metrics-7d10382c1025
- 搜尋結果要明確、不模糊: recall@k, precision@k, MRR) 等等
- 會有多個搜尋結果都很適合丟給使用者: DCG, nDCG 等等
- “Boss” metrics: 老闆半夜丟訊息給你「為什麼這個詞搜尋結果出來這麼爛?」
- 跟使用者有關還是商業策略有關?
- 如果都不是,跟老闆適當解釋你們的衡量系統
如果沒有「衡量資料」只靠福至心靈 spot check,等一下寫的 ES 工程沒辦法做最佳化。
指標需要 PM 提供。評量資料需要 PM 跟開發者一起研究。
Elasticsearch 技術 #
- 多看官方文件,例如
- 搜尋分兩階段:recall 跟 ranking, 要先能匹配到,才有算分排名的機會
- 搜尋跟兩者有關:「怎麼建索引」跟「怎麼下 query」
analyzer
影響 recall- 決定索引裡面的資料要怎麼處理(大小寫?斷詞?去掉符號?)
search_analyzer
則是用在處理使用者即時的 query。通常analyzer
跟search_analyzer
應該要一樣的處理方式,避免搭不起來的副作用。但 jieba 中文斷詞是個例外,文本資料會希望更多可能性 (緣由見 https://github.com/fxsjy/jieba 全模式)- 不同的欄位可以、也最好有各別的 analyzer
- 善用
/_analyze
了解 debug 一個 analyzer 對於一串文字的處理結果 - 中文斷詞要處理,雖然 jieba elasticsearch plugin 不見得好用,必要的時候需要自己魔改使用繁體字典或客製化字典
- 多欄位
- 可用
cross_fields
+multi_match
去匹配多個欄位 - 每個欄位不同的 “type” (keyword vs. text) 準確搜尋跟文本搜尋可以併用,並以不同的分數合併
- 可用
- 分數調整
- 排名的分數有兩大類:資料本身的重要性 (跟著 document, 與 query 無關,靜態的重要度) ,以及 query 跟資料的相關性 (runtime 算出)
- 靜態分數、重要度:事先根據商業邏輯算好,在建造 index 的時候放在文件的一個/多個欄位
- 整體分數可以自己寫公式,把靜態分數與不同欄位的相關分數融合在一起
- 匹配的時候,每個欄位可以有權重自調
- 善用 must, should, filter, 以及
minimum_should_match
的組合 - 但要注意,避免太多 should 讓 recall 過多,或是用奇怪的公式,導致搜尋速度變慢
- 善用
/_search?explain=true
找問題,看匹配的理由與分數的組成 (BM25 is tricky, synonym is also tricky. 為了 recall 塞太多資料可能會傷害 ranking) - 如果延遲時間允許或是 API 設計得好,一個使用者的 query 可以做多次多種準確度的搜尋,最後把結果合併起來
- Embedding 雖然可以考慮,不過不一定適合短文件(例如 POI),需要科學方法測量評估,而測量需要資料
- Operation 跟 scalability
若您覺得有趣, 請
追蹤我的Facebook 或
Linkedin,
讓你獲得更多資訊!