分詞、匹配、相關性、排序運算式
針對目前若干使用者遇到的搜尋結果與預期不符合的問題進行統一詳細說明,並以此為話題展開說明下OpenSearch在搜尋效果方面的功能和後續一些工作方向。
首先,對於搜尋來講,最常見的有兩種做法:
資料庫的like查詢,可以理解為簡單的內含項目關聯性;
百度、google等搜尋引擎,涉及到分詞,將查詢詞根據語義切分成若干片語term(這個是搜尋引擎重痛點之一),通過term組合匹配給相應文檔進行打分,根據分值排序,並最終返回給使用者。
OpenSearch採用的方式與上述搜尋引擎做法基本一致。那這裡就有三部分內容會影響搜尋效果:1,分詞方式;2,匹配方式;3,相關性算分。
我們來分別說下這三部分在OpenSearch上的行為和表現。
接下來,我們詳細說明下各個欄位的展現效果及適用情境,供大家參考。
分詞方式
熟悉各類分詞是本篇操作的前提,請務必先查閱 內建分析器文檔。
匹配方式
原理
分完詞後得到若干term,如何召迴文檔,就涉及到匹配方式。目前OpenSearch內部預設支援的是AND,即一篇文檔中包含全部的term才能被搜尋出來。當然這是對同一關鍵詞而言的,除此之外系統還支援多種匹配方式,如AND、OR、RANK、NOTAND以及(),優先順序從高到低為(),ANDNOT,AND,OR,RANK。
舉例
關係 | 用法 | 含義 |
query=title:”蘋果 手機” | 查詢title中包含蘋果和手機的文檔 | |
AND | query=title:’蘋果’ AND cate:’手機’ | 交集。查詢title中包含蘋果,且cate包含手機的文檔 |
OR | query=title:’蘋果’ OR cate:’手機’ | 並集。查詢title中包含蘋果,或cate包含手機的文檔 |
RANK | query=title:’蘋果’ RANK cate:’手機’ | 查詢title中包含蘋果的文檔,如果cate包含手機則可以加分 |
ANDNOT | query=title:’蘋果’ ANDNOT cate:’手機’ | 查詢title中包含蘋果,但cate不包含手機的文檔 |
案例
問:我文檔中包含“吃飯了”,我搜尋“吃飯”、“吃飯了”都能召回,搜尋“吃飯了嗎”沒結果?
答:因為目前OpenSearch是要求全部的分詞結果都匹配才能召迴文檔,上面的“嗎”在文檔中沒有出現,所以無法召回。但可以通過查詢分析解決。
問:我只想尋找某些詞排在最前面的文檔,比如以“肯德基”開頭的文檔;答:目前不支援位置相關召回。
相關性算分
上面提到的都是跟召回相關的技術,召迴文檔之後,究竟文檔如何排序就涉及到相關性。目前OpenSearch有sort子句來支援使用者自訂排序。如果不設定sort,則預設為sort=-RANK;sort本身支援多維排序,以及升降序的支援。比如sort=-RANK;+bonus,意思為第一位按照相關性降序排序,相關性分值一樣的文檔再按照bonus升序排列。這裡我們重點描述下RANK的用法,RANK即為OpenSearch中的相關性設定,主要分為兩部分:基礎排序(粗排)和業務排序(精排)。
原理
OpenSearch相關性算分策略為,取召回的rank_size(目前是100萬)個文檔按照粗排運算式的定義進行算分;取粗排分最高的N個結果(百層級)按照精排運算式進行算分,並排序;然後根據start與hit的設定取相應結果返回給使用者。如果使用者擷取的結果超過了精排結果數N,則後續按照粗排分數排序結果繼續展現。
基礎排序-(粗排)運算式:從上面原理介紹中可以看出粗排對效能(latency)的影響非常大,但同時粗排又非常的重要,否則會出現好的文檔無法進入精排而導致文檔不能被最終展現。所以粗排要盡量的簡單有效,目前OpenSearch的粗排只支援幾個簡單的正排欄位、靜態bm25、時效分等因素。
業務排序-(精排)運算式:通過粗排運算式篩選出較優質的N個文檔進行詳細排序,精排運算式中支援複雜的數學計算、邏輯等,並且OpenSearch提供了豐富的典型情境(如O2O類)的function和feature來滿足日常的相關性需求。
同時,系統以內建了多個情境的應用結構和排序運算式,可以供大家參考和使用。
舉例
情境 | 運算式 | 含義 |
論壇-粗排 | static_bm25() | 簡略文本分 |
論壇-精排 | text_relevance(title)*3+text_relevance(body) + if(text_relevance(title)>0.07,timeliness(create_timestamp),timeliness(create_timestamp)*0.5) + (topped+special+atan(hits)*0.5+atan(replies))*0.1 | 文本分 、 時效分 、 其他屬性分 |
O2O-粗排 | sold_score+general_score*2 | 銷量、門店綜合分值(離線算好) |
O2O-精排 | 2*sold_score+0.5*reward - 10*distance(lon,lat,u_posx,u_posy) + if ((flags&2) =2, 2, 0)+if(is_open=5,10,0) + special_score | 銷量、配送速度及準點率 、 距離 、 是否繁忙、是否在上班時間 、 人工幹預 |
小說-粗排 | static_bm25()*0.7+hh_hot*0.00003 | 文本分、熱度 |
小說-精排 | pow(min(0.5,max(text_relevance(category),max(text_relevance(title), text_relevance(author)))),2) + general_score*2 + 1.5*(1/(1+pow(2.718281,-((log10(hh_hot)-2)*2-5))))) | 分類相關性、標題相關性、作者相關性 、 小說品質 、 小說熱度 |
電商-粗排 | static_bm25()+general_score*2+timeliness(end_time) | 文本分、寶貝綜合分值、到期時間 |
電商-精排 | text_relevance(title)*3+text_relevance(category) + general_score*2+boughtScore*2 + tag_match(ctr_query_value,doc_value,mul,sum,false,true)+.. | 文本相關性、類目相關性 、 寶貝人氣、賣家分 、 ctr預估、特徵規則分等 |
案例
問:精排運算式text_relevance(seller_id)報找不到欄位答:text_relevance()只支援TEXT及SHORT_TEXT類型,其他不可以。
問:查詢報2112錯誤,是什麼問題?答:查詢語句(query子句)必須與formula相配合,比如query=default:’keyword’,default中包含title和body欄位,而formula指定text_relevance(title)+text_relevance(author)則會報錯,因為author在default中不存在。
提示
排序運算式的算分是在查詢結算對每個文檔進行計算的,所以如果跟查詢無關的部分的計算可以預先離線計算好,新增一個general_score欄位來存放,排序的時候只要使用general_score欄位即可,避免大量計算過程,提高查詢效能。
tag_match的feature允許使用者將query中的特徵與doc中特徵做多維運算,在電商情境下有著非常廣泛的用途,有類似的需求的使用者可以研究下。
OpenSearch提供了豐富的function和feature,使用得當可以獲得非常強大的功能。
相關性有很多部分共同組成,各項之間的權重需要根據搜尋排序效果不斷進行調整以達到一個使用者滿意的搜尋效果。