借鉴:https://blog.csdn.net/wslyk606/article/details/84315862?spm=1001.2014.3001.5506
1 引言
项目中es库中存储了大量的文档信息,而且是分段存储。
需求:根据文档内容检索出当前的文档。
问题:检索出了大量的相同文档,如何去重呢?
大量相同文档伴生的问题:
es检索到10000条以上数据就会抛错
java Api中只能显示10条检索出来的数据
2 Elasticsearch去重功能
2.1 关系型数据库如何去重
关系型数据库中,比如MySQL,可以通过distinct进行去重,一般分为两种:
1 ) 统计去重后的数量
select distinct(count(1)) from test;
2 ) 获取去重后的结果
select distinct name,sex from person;
test,person为对应的表名。
2.2 es如何去重
1 ) es查询结果进行去重计数
es的去重计数工卡可以通过es的聚合功能+Cardinality聚合函数来实现
2 ) es查询结果去重后显示
去重显示有两种方式:
(1) 使用字段聚合+top_hits聚合方式
(2)使用collapse折叠功能(5.3后版本提供)
我这里使用的es是2.4的版本,JavaApi使用的是第一种方式,5.x,6.x的版本也可以使用
2.3 es折叠去重
这里介绍es的折叠去重,原因是简单,性能好。
注意:collapse的字段需要为keyword或者number类型。
POST your_index/_search
{
"query":{
"match_all":{
}
},
"collapse":{
# 根据哪个字段去去重 uid
"field":"uid"
}
}
java代码 es6.5.4版本
RestHighLevelClient client = esClient.getElasticsearchClient();
SearchRequest request = new SearchRequest(index);
request.types(type);
// 构建查询器
SearchSourceBuilder builder = new SearchSourceBuilder();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
// 需要去重的字段
CollapseBuilder collapseBuilder = new CollapseBuilder("fileId");
// 复合查询
if (ObjectUtil.isNotNull(esQueryParamPaginationBo.getUserId())) {
boolQuery.must(QueryBuilders.matchQuery("userId", esQueryParamPaginationBo.getUserId()));
}
if (StrUtil.isNotBlank(esQueryParamPaginationBo.getFileName())) {
boolQuery.must(QueryBuilders.matchQuery("fileName", esQueryParamPaginationBo.getFileName()));
}
if (StrUtil.isNotBlank(esQueryParamPaginationBo.getContent())) {
boolQuery.must(QueryBuilders.matchQuery("content", esQueryParamPaginationBo.getContent()));
}
if (StrUtil.isNotBlank(esQueryParamPaginationBo.getTransContent())) {
boolQuery.must(QueryBuilders.matchQuery("transContent", esQueryParamPaginationBo.getTransContent()));
}
// 组装查询条件
builder.query(boolQuery).size(querySize);
builder.collapse(collapseBuilder);
// 组装请求
request.source(builder);
// 发送请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);