去重实现原理: 采用es 的Collapse折叠+cardinality基数计算 实现去重
1、优点:简单快速效率高,几乎无性能损耗(相比于分桶去重)
2、缺点:
1)Collapse折叠只支持一个字段去重,且字段必须是 keyword
2)cardinality基数计算去重后数量 (采用hyperloglog实现,hyperloglog一种近似计算)会有误差,
3) 不支持search_after 和 scroll,有深度分页问题

1、单个字段去重

GET /xxxxx/_search
{  "_source": [   //查询显示的字段
        "title",
        "uuid",
        "id"
      ],
   "query": {
    "match_phrase": {
      "title": "去重查询"
    }
  },
  "sort": [
    {
      "id.keyword": {
        "order": "desc"
      }
    }
  ],
  "collapse": {  
    "field": "uuid.keyword",//折叠字段,即 去重字段(折叠只支持一个字段)
    "inner_hits": {   //内部查询可以省略
      "name": "inner_tops",//内部查询的名字
      "size": 2,       //折叠项 取几个
      "sort": [    //折叠 内部排序字段
        {
          "id.keyword": "desc"
        }
      ],
      "collapse": { "field": "title.keyword" },//二次折叠
      "_source": [   //内部查询显示的字段
        "title",
        "uuid",
        "id"
      ]
    }
  },
  "aggs": {
    "total_size": {   //聚合桶名称
      "cardinality": {  //折叠 total 数量不发生变化,采用cardinality 获取总数量
        "field": "uuid.keyword" 
        "precision_threshold": 100   //精确度,0-40000 
      }
    }
  },
  "track_total_hits":true  //返回所有条数结果,默认返回10000
}
java API
//折叠和cardinality   去重 查询
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
AggregationBuilder aggregation = AggregationBuilders.cardinality(“total_size”).field("uuid.keyword");
searchSourceBuilder.aggregation(aggregation);

Aggregations aggregations = searchResponse.getAggregations();
Cardinality cardinality = aggregations.get(“total_size”);
System.out.println(cardinality.getValue())
   Elasticsearch 8.0+ 新版api 
   BoolQuery.Builder boolQuery = new BoolQuery.Builder();
   SearchResponse<JSONObject> search = elasticsearchClient.search(builder ->
                                builder.index(EsIndexConstants.INDEX_NAME).query(q ->
                                                q.bool(boolQuery.build()))
                                        .from(start)
                                        .size(requestInfo.getPageSize())
                                        .collapse(new FieldCollapse.Builder().field("uuid.keyword").build())
                                        .sort(s -> s.field(f -> f.field("publish_time").order(SortOrder.Desc))
                                       	//
                                        .aggregations("total_size", a-> a.cardinality(b->b.field("uuid.keyword").precisionThreshold(100))
                                        )
                                        .trackTotalHits(t -> t.enabled(true))
                        , JSONObject.class);
 //获取折叠后的总数                       
long totalSize=search.aggregations().get("total_size").cardinality().value();

2、多个字段去重
将多个字段组合成 一个字段然后去重
多个字段组合成一个字段有3种方案
1)写入的时候组合
2)采用pinpline
3)采用script 脚本

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐