文章目录
1 入门程序
通过入门程序,简单的对搜索Java API有一个整体的认识。来个基本的搜索:
GET books/_search
{
"query": {
"match_all": {}
}
}
package study.wyy.esclient.high.search;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.junit.Test;
import study.wyy.esclient.high.BaseTest;
import java.io.IOException;
/**
* @author wyaoyao
* @description
* @date 2021/1/12 16:58
*/
@Slf4j
public class Demo extends BaseTest {
@Test
public void testSync() throws IOException {
// 1 构建搜索请求 SearchRequest
SearchRequest request = buildSearchRequest();
// 2 执行请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 获取hits
SearchHits hits = response.getHits();
// 获取搜索结果的数量
long totalHits = hits.getTotalHits().value;
// 获取最高的得分
float maxScore = hits.getMaxScore();
// 获取搜索结果的相关性数据
TotalHits.Relation relation = hits.getTotalHits().relation;
// 搜索结果
SearchHit[] result = hits.getHits();
// 日志输出,这里我给转成json了
log.info(new ObjectMapper().writer().writeValueAsString(response));
}
public SearchRequest buildSearchRequest(){
// 1 构建搜索请求 SearchRequest
SearchRequest request = new SearchRequest();
// 1.1 指定索引库,可变参数可指定多个,也可以不指定,那就是全部索引都搜索
request.indices("books");
// 1.2 大部分搜索参数都可以通过SearchSourceBuilder构建
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 1.3 设置查询条件: 将"全部匹配(match_all)"添加到查询中
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
// 1.4 将searchSourceBuilder添加到SearchRequest中
request.source(searchSourceBuilder);
return request;
}
}
一个返回示例:
{
"internalResponse":{
"numReducePhases":1,
"fragment":true
},
"scrollId":null,
"totalShards":3,
"successfulShards":3,
"skippedShards":0,
"shardFailures":[
],
"clusters":{
"total":0,
"successful":0,
"skipped":0,
"fragment":true
},
"hits":{
"hits":[
{
"score":1,
"id":"1",
"type":"_doc",
"nestedIdentity":null,
"version":-1,
"seqNo":-2,
"primaryTerm":0,
"highlightFields":{
},
"sortValues":[
],
"matchedQueries":[
],
"explanation":null,
"shard":null,
"index":"books",
"clusterAlias":null,
"sourceAsMap":{
"author":"Bruce Eckel",
"price":70.2,
"publish_time":"2007-10-01",
"description":"Java学习必读经典,殿堂级著作!赢得了全球程序员的广泛赞誉。",
"language":"java",
"id":"1",
"title":"Java编程思想"
},
"innerHits":null,
"fields":{
},
"sourceAsString":"{"id":"1","title":"Java编程思想","language":"java","author":"Bruce Eckel","price":70.2,"publish_time":"2007-10-01","description":"Java学习必读经典,殿堂级著作!赢得了全球程序员的广泛赞誉。"}",
"rawSortValues":[
],
"sourceRef":{
"fragment":true
},
"fragment":false
}
],
"totalHits":{
"value":4,
"relation":"EQUAL_TO"
},
"maxScore":1,
"sortFields":null,
"collapseField":null,
"collapseValues":null,
"fragment":true
},
"terminatedEarly":null,
"profileResults":{
},
"numReducePhases":1,
"took":{
"hours":0,
"minutes":0,
"seconds":0,
"millis":0,
"stringRep":"0ms",
"nanos":0,
"days":0,
"micros":0,
"millisFrac":0,
"secondsFrac":0,
"hoursFrac":0,
"microsFrac":0,
"daysFrac":0,
"minutesFrac":0
},
"failedShards":0,
"aggregations":null,
"timedOut":false,
"suggest":null,
"fragment":false
}
2 API基本介绍
2.1 SearchRequest
SearchRequest可用于搜索文档,聚合文档,Suggest有关的任何操作,SearchRequest是必须要构建的基本对象。
可以通过这个对象设置基本的参数,比如:
SearchRequest request = new SearchRequest();
// 1 指定索引库: 可变参数,可指定多个索引库
request.indices(new String[]{"index1","index2","index3"});
// 2 添加搜索条件,大多数搜索参数都是通过SearchSourceBuilder构建,后面会进行介绍
request.source(new SearchSourceBuilder());
// 3 设置路由参数: 可变参数,可设置多个
request.routing(new String[]{"routing1", "routing1"});
// 4 设置控制如何处理不可用的具体索引(已关闭或缺少)
request.indicesOptions(IndicesOptions.lenientExpand());
// 5 设置首选参数: 例如,执行搜索首选本地分片。默认是在分片之间随机
request.preference("_local");
2.2 SearchSourceBuilder
基础设置项
大多数搜索参数都是通过SearchSourceBuilder构建,比如设置查询条件,设置搜索结果的起始偏移位置(from),设置返回的命中个数(size,默认是10),超时时间等
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 1 设置查询条件: 通过QueryBuilder进行构建,es提供了QueryBuilders类帮助我们构建QueryBuilder的实现
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
// 2 设置搜索结果的起始偏移位置
searchSourceBuilder.from(0);
// 3 设置返回的命中结果数量,默认是10
searchSourceBuilder.size(20);
// 4 设置一个超时时间
searchSourceBuilder.timeout(TimeValue.timeValueSeconds(20));
// 添加到SearchRequest
SearchRequest request = new SearchRequest();
request.source(searchSourceBuilder);
设置查询条件
设置查询条件: 通过QueryBuilder进行构建,es提供了QueryBuilders类帮助我们构建QueryBuilder的实现,QueryBuilder是基于es的DSL查询实现的。
设置排序策略
- 排序策略是通过SortBuilder对象描述的
- SearchSourceBuilder 允许用户添加多个SortBuilder实例
SortBuilder有四个特殊实现,常用的就是前两个了吧
- FieldSortBuilder: 字段排序
- ScoreSortBuilder: 得分排序
- GeoDistanceSortBuilder: 地理位置排序
- ScriptSortBuilder
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 构建SortBuilder实例
// 按分数降序排序(这也是默认排序)
searchSourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC));
// 按照id升序
searchSourceBuilder.sort(new FieldSortBuilder("_id").order(SortOrder.ASC));
source filter
默认是会返回文档的源内容(source字段),与Rest API一样,客户端可以配置是否返回,还是返会指定字段。
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 关闭返回source,默认是true
searchSourceBuilder.fetchSource(false);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 设置返回指定字段
String[] excludes = {"filed1", "filed2"};
String[] includes = {"filed3", "filed4"};
searchSourceBuilder.fetchSource(includes,excludes);
高亮显示
可以通过HighlightBuilder来设置高亮显示搜索结果。
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 设置高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
// title字段设置高亮
HighlightBuilder.Field title = new HighlightBuilder.Field("title");
// 设置高亮类型:unified(默认), plain , fvh
title.highlighterType("unified");
// 添加到highlightBuilder;
highlightBuilder.field(title);
// 可以设置多个
// title字段设置高亮
HighlightBuilder.Field author = new HighlightBuilder.Field("author");
// 设置高亮类型:unified(默认), plain , fvh
author.highlighterType("unified");
// 添加到highlightBuilder;
highlightBuilder.field(author);
// 添加到SearchSourceBuilder
searchSourceBuilder.highlighter(highlightBuilder);
聚合
在搜索的时候,客户端还可以设置请求聚合结果
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
AvgAggregationBuilder field = AggregationBuilders.avg("avg_price").field("price");
searchSourceBuilder.aggregation(field);
建议请求
常见的场景就是,使用百度搜索时候的联想搜索:
需要将SuggestBuilder实例添加到SearchSourceBuilder中
- SuggestBuilders工具类可以方便的构建SuggestBuilder
eg:
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 为title字段,添加java的Suggestions
TermSuggestionBuilder termSuggestionBuilder = SuggestBuilders.termSuggestion("title").text("java");
// 将TermSuggestionBuilder添加SuggestBuilder中,并为其命名
SuggestBuilder suggestBuilder = new SuggestBuilder();
suggestBuilder.addSuggestion("suggestions_title",termSuggestionBuilder);
// SuggestBuilder添加到SearchSourceBuilder
searchSourceBuilder.suggest(suggestBuilder);
分析查询和聚合
es提供了Profile API,帮助客户端端分析每次检索各个环节所用的时间
// 默认是false
searchSourceBuilder.profile(true);
2.3 执行请求
同样还是支持两种方式:同步和异步
- 同步
SearchRequest request = new SearchRequest();
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
- 异步
SearchRequest request = new SearchRequest();
client.searchAsync(request, RequestOptions.DEFAULT, new ActionListener<SearchResponse>() {
@Override
public void onResponse(SearchResponse searchResponse) {
// 执行成功时的回调
}
@Override
public void onFailure(Exception e) {
// 执行发生异常时的回调
}
});
2.3 解析响应结果(SearchResponse)
SearchResponse中提供了有关搜索执行本身以及返回文档的详细信息,如http状态码,执行时间,请求是提前终止还是超时等。
基本返回项
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
SearchRequest request = new SearchRequest();
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// http状态码
RestStatus status = response.status();
// 执行时间
TimeValue took = response.getTook();
// 请求是否提前停止
Boolean terminatedEarly = response.isTerminatedEarly();
// 请求是否超时
boolean timedOut = response.isTimedOut();
影响的分片
获取搜索影响的分片总数,以及成功的与失败的分片的统计信息,也包括了有关分片级别的执行信息。对于请求执行失败的信息,可以通过解析ShardSearchFailure来处理
SearchRequest request = new SearchRequest();
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 查看搜索影响总的分片数
int totalShards = response.getTotalShards();
// 搜索成功的分片数量
int successfulShards = response.getSuccessfulShards();
// 搜索失败的分片数量
int failedShards = response.getFailedShards();
// 请求失败的执行信息
ShardSearchFailure[] shardFailures = response.getShardFailures();
ShardSearchFailure shardFailure = shardFailures[0];
// 拿到异常信息
Throwable cause = shardFailure.getCause();
// 分片id
int i = shardFailure.shardId();
// 失败原因
String reason = shardFailure.reason();
// 索引库
shardFailure.shard().getIndex
获取基本的搜索结果
SearchHits封装了搜索结果的相关的所有信息。如何获取如下:
SearchHits hits = response.getHits();
SearchHits封装了搜索结果的相关的所有信息,比如获取最高得分,获取命中的总数量
TotalHits totalHits = hits.getTotalHits();
// 搜索结果的数量
long value = totalHits.value;
// 搜索结果的相关性数据
TotalHits.Relation relation = totalHits.relation;
// 本次搜索的最高得分
float maxScore = hits.getMaxScore();
// 获取本次的搜索的排序字段
SortField[] sortFields = hits.getSortFields();
// 获取搜索命中的结果
SearchHit[] searchHits = hits.getHits();
SearchHit: 封装了文档的基本信息,比如索引名称,文档id,搜索的得分等
// 文档索引
String index = searchHit.getIndex();
// 文档id
String id = searchHit.getId();
// 集群别称
String clusterAlias = searchHit.getClusterAlias();
// 得分
float score = searchHit.getScore();
// 获取source字段,也就是文档的具体内容(键值对形式)
Map<String, Object> sourceAsMap = searchHit.getSourceAsMap();
// 获取source字段,也就是文档的具体内容 json格式
String sourceAsString = searchHit.getSourceAsString();
获取高亮信息
SearchHit还封装了高亮显示的结果
// 获取高亮字段
Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
HighlightField highlightField = highlightFields.get("字段名");
// 获取包含高亮显示字段内容的一个或者多个片段
Text[] fragments = highlightField.getFragments();