全部产品
Search
文档中心

智能开放搜索 OpenSearch:distinct子句

更新时间:Jan 05, 2024

打散子句可以在一定程度上保证展示结果的多样性,以提升用户体验。如一次查询可以查出很多的文档,但是如果某个用户的多个文档分值都比较高,则都排在了前面,导致一页中所展示的结果几乎都属于同一用户,这样既不利于结果展示也不利于用户体验。对此,打散子句可以对每个用户的文档进行抽取,使得每个用户都有展示文档的机会。

语法说明

子句语法格式为:dist_key:field,dist_count:1,dist_times:1,reserved:false

参数

类型

必需

取值范围

默认值

描述

dist_key

string

要打散的字段

dist_times

int

1

抽取的轮数

dist_count

int

1

一轮抽取的文档数

reserved

true/false

true/false

true

是否保留抽取之后剩余的文档。如果为false,为不保留,则搜索结果的total(总匹配结果数)会不准确。

update_total_hit

true/false

true/false

false

当reserved为false时,设置update_total_hit为true,则最终total_hit会减去被distinct丢弃的数目(不一定准确),为false则不减。

dist_filter

string

过滤条件,被过滤的doc不参与distinct,只在后面的排序中,这些被过滤的doc将和被distinct出来的第一组doc一起参与排序。默认是全部参与distinct。

grade

float

指定档位划分阈值,所有的文档将根据档位划分阈值划分成若干档,每个档位中各自根据distinct参数做distinct,可以不指定该参数,默认是所有文档都在同一档。档位的划分按照文档排序时第一维的排序依据的分数进行划分,两个档位阈值之间用 “|” 分开,档位的个数没有限制。例如:1、grade:3.0 :表示根据第一维排序依据的分数分成两档,(< 3.0)的是第一档,(>= 3.0) 的是第二档;2、grade:3.0|5.0 :表示分成三档,(< 3.0)是第一档,(>= 3.0,< 5.0)是第二档,(>= 5.0)是第三档。档位的先后顺序和第一维排序依据的顺序一致,即如果第一维排序依据是降序,则档位也是降序,反之亦然。

dist_count和dist_times说明

以下样例用来解释和说明dist_count和dist_times的用法及含义:假设有6篇文档,id为主键,name为需要做打散的字段:

doc1: id:11 name:a

doc2: id:22 name:a

doc3: id:33 name:a

doc4: id:44 name:b

doc5: id:55 name:c

doc6: id:66 name:c

case1:distinct=dist_key:name,dist_count:2,dist_times:1,reserved:false表示抽取1轮,且一轮抽取2条文档。打散结果是:doc1 doc2 doc4 doc5 doc6

case2:distinct=dist_key:name,dist_count:1,dist_times:2,reserved:false表示抽取2轮,且每轮抽取1条文档。打散结果是:doc1 doc4 doc5 doc2 doc6

case3:distinct=dist_key:name,dist_count:1,dist_times:1,reserved:false表示抽取1轮,且一轮抽取1条文档。打散结果是:doc1 doc4 doc5

注意事项

  1. distinct为非必选子句。

  2. 在distinct中出现的字段必须在定义应用结构的同时配置为属性字段。

  3. 不支持array类型,只支持int和literal字段类型。

  4. 不支持指定多个 dist_key 。

  5. 目前排序没有自动去重的功能,但是可以通过distinct聚合实现去重的结果,例如:要对相同title的文章去重,将title设置为dist_key,抽取1轮,每轮抽取1个文档即可。

distinct uniq插件

如上面描述,如果reserved=false情况下,会导致搜索结果中的total及viewtotal不准确,如果用户需要依赖于这个值进行翻页或者其他处理,则会有问题。为此,系统提供了distinct uniq的插件来解决在dist_times:1,dist_count:1,reserved:false的情况下的total及viewtotal展示不准确。 在kvpair子句中添加duniqfield:field即可。 例:kvpairs=duniqfield:name

注意:

  • field必须与distinct子句中的dist_key一致。

  • 该插件仅在dist_times:1,dist_count:1,reserved:false查询下起作用,任何参数值有变化都将无效。

  • 出于性能考虑,目前该插件最大支持total值为5000,即使真实搜索结果数超过5000,也会返回5000。

  • 只有添加distinct uniq插件的,真实搜索结果数超过5000,也会返回5000,没有添加的不会只统计到5000。

  • 使用该插件并且查询命中数据量比较大(超百万级)的情况下,查询容易超时。

示例

  1. 查看create_time(创建时间)在1402301230之后且包含“浙大”的文档,并按照company_id字段进行打散抽取10轮,每轮取2个结果,抽取后的文档排在后面:

    query=default:'浙大'&&filter=create_time>1402301230&&distinct=dist_key:company_id,dist_count:2,dist_times:10
  2. 查看包含“浙大”的文档,且按照company_id字段进行打散抽取1轮,每轮取1个结果,抽取后的文档丢弃(要求返回结果数为丢弃后的):

    query=default:'浙大'&&distinct=dist_key:company_id,dist_count:1,dist_times:1,reserved:false&&kvpairs=duniqfield:company_id