distinct子句
功能說明
打散子句可以在一定程度上保證展示結果的多樣性,以提升用戶體驗。如一次查詢可以查出很多的文檔,但是如果某個用戶的多個文檔分值都比較高,則都排在了前面,導致一頁中所展示的結果幾乎都屬于同一用戶,這樣既不利于結果展示也不利于用戶體驗。對此,打散子句可以對每個用戶的文檔進行抽取,使得每個用戶都有展示文檔的機會。
子句語法
distinct=dist_key:field,dist_count:1,dist_times:1,reserved:false
參數(shù)說明:
dist_key:必選參數(shù),要打散的屬性字段。
dist_times:可選參數(shù),抽取的輪數(shù),默認為1。
dist_count:可選參數(shù),一輪抽取的文檔數(shù),默認為1。
reserved:可選參數(shù),true/false,是否保留抽取之后剩余的文檔,默認為true。如果為false,為不保留,則搜索結果的total(總匹配結果數(shù))會不準確。
update_total_hit:可選參數(shù),true/false,默認為false。當reserved為false時,設置update_total_hit為true,則最終total_hit會減去被distinct丟棄的數(shù)目(不一定準確),為false則不減。
dist_filter:可選參數(shù),過濾條件,被過濾的doc不參與distinct,只在后面的排序中,這些被過濾的doc將和被distinct出來的第一組doc一起參與排序。默認是全部參與distinct。
grade:可選參數(shù),指定檔位劃分閾值,所有的文檔將根據(jù)檔位劃分閾值劃分成若干檔,每個檔位中各自根據(jù)distinct參數(shù)做distinct,可以不指定該參數(shù),默認是所有文檔都在同一檔。檔位的劃分按照文檔排序時第一維的排序依據(jù)的分數(shù)進行劃分,兩個檔位閾值之間用 “|” 分開,檔位的個數(shù)沒有限制。例如:1、grade:3.0 :表示根據(jù)第一維排序依據(jù)的分數(shù)分成兩檔,(< 3.0)的是第一檔,(>= 3.0) 的是第二檔;2、grade:3.0|5.0 :表示分成三檔,(< 3.0)是第一檔,(>= 3.0,< 5.0)是第二檔,(>= 5.0)是第三檔。檔位的先后順序和第一維排序依據(jù)的順序一致,即如果第一維排序依據(jù)是降序,則檔位也是降序,反之亦然。
示例:
distinct=dist_key:company_id,dist_count:2,dist_times:10
備注:按照company_id字段進行打散抽取10輪,每輪取2個結果,抽取后的文檔排在后面
dist_count和dist_times說明:
以下樣例用來解釋和說明dist_count和dist_times的用法及含義:
假設有6篇文檔,id為主鍵,name為需要做打散的字段:
doc 1: id:1 name:a
doc 2: id:2 name:a
doc 3: id:3 name:a
doc 4: id:4 name:b
doc 5: id:5 name:c
doc 6: id:6 name:c
case1:
distinct=dist_key:name,dist_count:2,dist_times:1 打散結果是:doc1 doc2 doc4 doc5 doc6
case2:
distinct=dist_key:name,dist_count:1,dist_times:2 打散結果是:doc1 doc4 doc5 doc2 doc6
case3:
distinct=dist_key:name,dist_count:1,dist_times:1 打散結果是:doc1 doc4 doc5
?
多階段distinct
現(xiàn)在召回引擎版實例的searcher上的排序可以分為兩個大的階段,粗排和精排,其中精排的輪數(shù)視用戶配置的scorer的個數(shù)而定。多階段的distinct是指用戶除了可以在排序階段(粗排)做distinct以外,還可以對排序之后的結果集再追加一輪distinct。不妨將這兩種distinct分別稱為排序時distinct和排序后distinct。多階段的distinct允許用戶指定在對所有query命中的結果做完distinct后再對粗排和精排后的結果做一次distinct的,比如第一階段的distinct使用一個較粗粒度的distinct,即具有較大的dist_count,保證每個key都有足夠多的結果,第二階段的distinct再做一個較小的粒度的distinct。多階段的distinct還允許用戶指定在粗排時不做distinct,在粗排和精排后再做一輪distinct
Note
如果指定了在粗排和精排后追加一輪distinct,在query中(start + hit)大于scorer的rank_size的時候,翻頁是不穩(wěn)定的。
多階段distinct語法如下:distinct = sub_distinct_clause_when_sort;sub_distinct_clause_after_sort其中,sub_distinct_clause_when_sort為排序時distinct clause;sub_distinct_clause_after_sort為排序后distinct clause。
按照語法規(guī)則,多階段distinct有如下三種形式:
distinct = sub_dist_clause;none_sub_dist_clause排序時distinct按照sub_dist_clause中定義做打散;排序后不做打散。例如:"distinct=dist_key:company_id,dist_count:1,dist_times:1;none_dist"
distinct = sub_dist_clause1;sub_dist_clause2排序時distinct按照sub_dist_clause1中定義做打散;排序后distinct按照sub_dist_clause2中定義做打散。例如:
"distinct=dist_key:company_id,dist_count:2,dist_times:1;dist_key:company_id,dist_count:1,dist_times:1"
distinct = none_sub_dist_clause;sub_dist_clause排序時不做打散;排序后distinct按照sub_dist_clause中定義做打散。例如:"distinct=none_dist;dist_key:company_id,dist_count:1,dist_times:1"
distinct = sub_dist_clause如果只有一個dist子句,在粗排和排序后階段都會按照sub_dist_clause中定義做打散。例如:"distinct=dist_key:company_id,dist_count:1,dist_times:1"而disctinc = none_sub_dist_clause; none_sub_dist_clause這種形式是不合法的。因為如果排序時和排序后都不做distinct,那么distinct子句就沒有意義了
distinct uniq插件
如上面描述,如果reserved=false情況下,會導致搜索結果中的total及viewtotal不準確,如果用戶需要依賴于這個值進行翻頁或者其他處理,則會有問題。為此,系統(tǒng)提供了distinct uniq的插件來解決在dist_times:1,dist_count:1,reserved:false的情況下的total及viewtotal展示不準確。
在kvpairs中添加duniqfield:field即可。例:kvpairs=duniqfield:name
注意:
field必須與distinct子句中的dist_key一致;
該插件僅在dist_times:1,dist_count:1,reserved:false查詢下起作用,任何參數(shù)值有變化都將無效。
出于性能考慮,目前該插件最大支持total值為5000,即使真實搜索結果數(shù)超過5000,也會返回5000。
示例:
distinct=dist_key:company_id,dist_count:1,dist_times:1,reserved:false&&kvpairs=duniqfield:company_id
注意事項
distinct為非必選子句;
在distinct中出現(xiàn)的字段必須在定義應用結構的時配置為屬性字段。
不支持array類型,只支持int和literal字段類型。
不支持指定多個 dist_key 。