distinct子句

功能说明

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

子句语法

"distinct" : {
     "default": {  
      "dist_key" : "field",
      "dist_count":number,
      "dist_times" : number,
      "dist_filter" : "filter_expression",
      "reserved" : boolean,
      "max_item_count" : number,
      "grade" : []
    },
    "rank": {  
      "dist_key" : "field",
      "dist_count":number,
      "dist_times" : number,
      "dist_filter" : "filter_expression",
      "reserved" : boolean,
      "max_item_count" : number,
      "grade" : []
    },
    "rerank": {
      "dist_key" : "field",
      "dist_count":number,
      "dist_times" : number,
      "dist_filter" : "filter_expression",
      "reserved" : boolean,
      "max_item_count" : number,
      "grade" : []
    }
  }
}

为了保证打散效果,引擎默认在粗排和精排节点分别进行打散。在打散时可以使用相同的打散规则,也可以分别指定不同的打散规则。不同阶段打散生效规则如下:

  • 仅指定default规则,粗排和精排都使用default进行打散。

  • 仅指定rank规则,仅粗排阶段进行打散。

  • 仅指定rerank规则,仅精排阶段进行打散。

  • 同时指定default和rank规则,粗排阶段用rank规则打散,精排阶段用default规则打散。

  • 同时指定default和rerank规则,粗排阶段用default规则打散,精排阶段用rerank规则打散。

  • 同时指定rank和rerank规则,粗排阶段用rank规则打散,精排阶段用rerank规则打散。

  • 同时指定default、rank和rerank规则,粗排阶段用rank规则打散,精排阶段用rerank规则打散。

  • default、rank、rerank三个规则必须指定一个。

打散规则参数说明

  • dist_key:必选参数,要打散的属性字段。

  • dist_count:可选参数,一轮抽取的文档数,默认为1。

  • dist_times:可选参数,抽取的轮数,默认为1。

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

  • reserved:可选参数,true/false,是否保留抽取之后剩余的文档,默认为true。如果为false,为不保留,则搜索结果的total(总匹配结果数)会不准确。

  • max_item_count:可选参数,设置计算distinct时最多保留的doc数目(最多保留数为max(max_item_count, hit))。

    • 为了最终结果翻页稳定,可以设置为最大可能查询到的文档数目(比如每页10条结果,最多翻页到100页,那么就设置为10*100=1000)。

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

示例:

"distinct" : {
     "default": {  
      "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" : {
     "default": {  
      "dist_key" : "name",
      "dist_count":2,
      "dist_times" : 1
    }
}
#打散结果是:doc1 doc2 doc4 doc5 doc6

case2:

"distinct" : {
     "default": {  
      "dist_key" : "name",
      "dist_count":1,
      "dist_times" : 2
    }
}
#打散结果是:doc1 doc4 doc5 doc2 doc6

case3:

"distinct" : {
     "default": {  
      "dist_key" : "name",
      "dist_count":1,
      "dist_times" : 1
    }
}
#打散结果是:doc1 doc4 doc5

distinct uniq插件

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

在kvpairs中添加duniqfield:field即可。

注意:

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

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

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

示例:

{
  "distinct" : {
    "default": {  
      "dist_key" : "company_id",
      "dist_count":1,
      "dist_times" : 1,
      "reserved" : false
    }
  },
  "kvpairs" : {
    "duniqfield":"company_id"
  }
}

注意事项

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

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