過濾和全文搜索
1)為什麼需要搜索層
過濾和全文搜索(FTS)可以快速訪問「意義上」的數據,而不僅僅是主要密鑰。正確設計的搜索層結合了以下內容:- 嚴格的過濾器(類別、日期、價格、訪問權限)
- 全文(詞匯匹配和排名)
- 立面(用於導航的聚合)
- 混合排名(BM25/TF-IDF+矢量栓塞)
- 強大的協議(光標分頁、TTL令牌、交叉分碼)
2)建築繪畫
組件:1.Ingest/ETL →規範化、重復數據消除、豐富、索引字段構建。
2.索引器→反索引(詞素→文檔),柱結構,矢量索引(HNSW/IVF-PQ)。
3.Query Layer →請求解析器、過濾器/訪問權限應用、shard調度程序、k-way merge。
4.Ranker → BM25+(opz。)LTR/Neural re-rank.
5.Serving →緩存、光標、立面、高線、自動配方。
6.可觀察性→潛伏度指標,質量,A/B實驗。
3)數據和索引模型
3.1字段和分析儀
類型:keyword(均勻匹配)、text(分析)、numeric/date/geo、vector。
分析儀:令牌化,正常化(lowercase, Unicode NFKC),過濾器(停止詞,stemming/lemmatization)。
多語言:按字段分析(ru,uk,en);ICU分析;音譯;考慮變音符號。
3.2反向索引(sparse)
結構:term → posting list(docID,term freq,位置)。
排名:具有現場助推器的BM25(或經典TF-IDF)。
3.3向量索引(dense)
文本的Embeddings(例如384-1024維)。
ANN結構:HNSW,IVF-PQ,平面(用於小集)。
余弦接近/內置產品;BM25校準(混合體)。
3.4面和單元
快速計數值的前奏/柱形存儲。
分層立面(類別/子類別)。
範圍(價格桶,日期)。
4)查詢: 過濾器+全文+排序
4.1個API合同(REST)
查詢:
GET /v1/search? q = classic slots & limit = 20 & cursor =... & sort = score: desc, created _ at: desc
&filters=brand:("NetEnt","EGT"); price:[10 TO 50];published_at:[2024-01-01 TO ]
&facets=brand,year,price:range(0,10,20,50,100)
答案(片段):
json
{
"items": [ { "id":"...", "title":"...", "score": 12. 3, "highlight": { "content": ["..."] } } ],
"facets": { "brand": [{"value":"NetEnt","count":123},...] },
"page": { "limit":20, "has_more":true, "next_cursor":"opaque-token" }
}
4.2 GraphQL(簡體)
graphql type Query {
search(query: String!, filter: SearchFilter, first: Int, after: String, sort: [Sort!]): SearchConnection!
}
4.3 gRPC
proto message SearchRequest {
string query = 1;
map<string,string> filters = 2;
int32 page_size = 3;
string page_token = 4; // курсор repeated string facets = 5;
}
5)自然語言處理(NLP)
令牌/正常化:Unicode安全,連字符/撇號計數。
停止單詞:按語言排列的調音列表。
Stemming vs lemmatization:對於ru/uk來說,lemmatization更好(質量>速度)。
同義詞:雙向/定向字典;TTL字典版本。
錯字(fuzzy):Damerau-Levenshtein具有距離限制和精確匹配的助推器。
N-grams/edge-ngrams:用於自動配方和提示。
音譯:「shch」 ↔ 「sht」,「kiev/kyiv」是對應規則。
6)相關性和排名
6.1基本詞匯評分
BM25按集合設置「k1」,「b」。
橫跨字段的助推器(標題^3,標題^1.5, body^1).
新鮮:「score+=freshness_boost(decay(created_at))」。
6.2行為信號
點擊率,dwell時間,保存到收藏夾中(帶有反位置巴亞斯)。
重復數據消除:將具有~相同內容的文檔(MinHash/SimHash)粘貼在一起。
6.3 Learning-to-Rank (LTR)
菲奇:田野BM25,長度,新鮮,人氣,短語匹配和位置爭吵。
型號:LambdaMART/XGBoost;離線指標NDCG@k,MAP,Precision@k;A/B在線。
6.4神經重新安排
兩步:recall (BM25/ANN) → top-N(例如200) → cross-encoder rerank。
成本核算:超時預算,在負載下沒有神經階段後退。
6.5混合搜索(sparse+dense)
Fusion(標量歸一化和總和)或多階段(dense為rerank)。
校準很重要:min-max/z-score/quantile映射。
7)過濾,面和訪問
7.1個過濾器
運算符:'=','IN',範圍,前綴,geo-bounding box/geo-distance。
組合:「AND」通過過濾器,「OR」在多個值內(品牌IN……)。
類型安全:數值字段不分析為文本。
7.2 Fasets
在預期的結構上廉價計數。
「應用」面板顯示剩余的變體(後過濾器面部)。
7.3訪問/多影子
安全過濾器集成到排名(預過濾器)之前。
文檔中字段的ABAC/RBAC(「tenant_id」,「visibility」,「acl」)。
請求令牌已簽名;多重特南特是自動「tenant_id」過濾器。
8)分離,遊標和一致性
在按時間排序時,通過「(得分,決勝局)」或「(created_at,id)」通過seek遊標進行分區。
不透明的「page_token」 c HMAC和TTL。
一致性:索引的近實時(NRT):延遲0。5-2與記錄和可見性之間。在SLA中記錄這一點。
Cross Shard:通過全局順序本地搜索→ k-way merge,令牌中的每包遊標。
9)自動補充和提示
Suggesters: prefix-trie / edge-ngrams по полю `title`.
Popular queries:點擊日誌→人氣線索+個性化(片段)。
Spell-as-you-type:具有距離限制'<=1'的快速fuzzy搜索。
GET /v1/suggest? q=kaz&limit=8&locale=ru
→ ["casino," "casual games,..."]
10)Highlight和snippets
位置索引→提取匹配的短語。
HTML屏蔽,長度限制,相鄰片段合並。
根據相關術語的密度對嗅覺進行排名。
11)性能、緩存和SLO
索引:內存中的熱段;郵寄壓縮;立面的doc values。
緩存:L1(過程),L2(Redis),立面/聚合緩存;根據索引版本殘疾。
SLO: P95 <150-200毫秒,「k<=20」,P99 <500毫秒;99的可用性。9%.
Backpressure:減少「k」,超載時關閉神經階段。
在API/用戶/tenant密鑰上排名限制。
12)可觀察性和質量指標
Techmetrics:- `search_latency_ms` (P50/P95/P99), `qps`, `timeouts`, `error_rate`
- `cache_hit_ratio`, `facet_cache_hit`, `rerank_share`
- `shard_fanout`, `merge_time_ms`, `ann_recall@k`
- NDCG@k,MAP,MRR,Recall@k,Precision@k在標記樣本中。
- CTR@k, sCTR (satisfied clicks), dwell time, отказ (pogostick rate).
A/B:捕獲「guardrail」度量(潛伏、錯誤)+目標(NDCG proxy)。
13)測試
Relevance unit tests:檢查關鍵請求的預期匹配。
基於屬性的:對打印錯誤/同義詞/語言的抗性。
分頁:頁面邊界上沒有重復內容(seek合同)。
安全性:訪問過濾器始終適用(即使在faset-count)。
字典倒退:同義詞和fuzzy規則的轉換。
14)安全和隱私
帶有PII的字段不作為文本索引;單獨存儲/加密。
最大程度地減少存儲的源文本(store=false,僅用於嗅探的字段)。
查詢隱私:不要用PII來計算原始查詢;匿名/散列。
多功能:嚴格的索引隔離或強制性的「tenant_id」過濾器。
15)遷移和互操作性
雙重記錄和逐步切換的索引方案(v1→v2)的轉換。
分析儀兼容性:保持舊鏈不被重新索引。
同義詞/停止單詞詞典的輪換:「version」,「activated_at」,rollback。
16)實用食譜
16.1經典詞匯搜索(BM25)
字段:「title^3」,「tags^2」,「body^1」。
分析儀:語言特定+語言化。
短查詢的Fuzzy(「<=3」令牌),「fuzziness=1」。
16.2 sparse+dense混合體
1.ANN搜索(k=200)
2.與top-200合並BM25
3.校準和排幹(Reciprocal Rank Fusion)
4.選擇top-N (N=20),可選地-以足夠的預算進行交叉編碼。
16.3面目錄導航
強硬的權利預過濾器/tenant
後過濾器筋膜(計入活動過濾器)
排序: 按相關性或業務領域(價格/新穎性)
17)查詢示例(偽DSL)
過濾器和排序:json
{
"query": "live casino,"
"filters": {
"country": ["EE","LV","LT"],
"license": ["MGA","UKGC"],
"launched_at": {"gte": "2023-01-01"}
},
"sort": ["_score:desc","launched_at:desc"],
"facets": ["country","license"],
"page": {"limit": 20, "cursor": "opaque"}
}
Geopoisk:
json
{
"query": "casino",
"geo": {"lat": 59. 437, "lon": 24. 753, "radius_km": 50}
}
自動配方:
json
{ "prefix": "evo", "field": "brand_suggest", "limit": 8 }
18) UX模式
有源過濾器芯片+「全部重置」。
空白結果:顯示「嘗試……」(同義詞,刪除過濾器)。
「零提示」:流行的查詢/類別。
遊標分區(「更多」按鈕)和無限滾動;應用過濾器的固定指示燈。
單獨的開關「考慮錯字」,「短語的精確匹配」。
19)頻繁的錯誤和反模式
排序時缺少決勝局→雙打/賽馬。
不考慮活動過濾器的面板→「假」計數。
排名後應用訪問過濾器。
通過單個分析儀混合不同的語言。
深層分區OFFSET/LIMIT代替seek遊標。
無限的fuzzy →潛伏期爆炸。
20)實施清單
1.定義字段及其類型,指定per-locale分析器。
2.設計反向索引+(opz.)向量ANN。
3.實現查詢解析器和安全訪問過濾器(預過濾器)。
4.調整BM25和現場助推器;連接筋膜。
5.輸入光標(opaque、HMAC、TTL)和k-way merge。
6.添加自動放大器、高亮度、安全屏蔽。
7.度量:潛伏期,NDCG@k,CTR;快取L1/L2。
8.A/B框架用於調諧相關性。
9.記錄SLA: NRT延遲、「極限」限制、一致性保證。
10.遷移計劃:索引,詞典和分析器的版本。
設計精良的過濾和全文搜索層不僅是一個快速的索引,而且還與光標,安全性,可預測的UX和可測量的相關性簽訂了明確的協議合同。這種方法可以擴展到數千到數十億份文檔,並支持經典詞匯搜索和具有神經網絡排名的現代混合場景。