1. Search API 查询
SearchRequest用于与搜索文档,聚集,建议有关的任何操作,并且还提供了在突出显示的文档上highlighting 显示的方式。
1.1 SearchRequest
/*
创建SearchRequest。如果没有参数,这将与所有索引冲突。
多数搜索参数已添加到SearchSourceBuilder中。它为搜索请求正文中的所有内容提供设置器。
将match_all查询添加到SearchSourceBuilder。
将SearchSourceBuilder添加到SearchRequest。
*/
SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
searchRequest.source(searchSourceBuilder);
// 可以在SearchSourceBuilder上设置大多数控制搜索行为的选项,其中或多或少包含与Rest API的搜索请求主体中的选项等效的选项。
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
searchRequest.indices("posts"); // 索引
sourceBuilder.query(QueryBuilders.termQuery("user", "kimchy"));
sourceBuilder.from(0);
sourceBuilder.size(5);
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
1.2 MatchQueryBuilder
- 搜索查询是使用QueryBuilder对象创建的。 Elasticsearch的Query DSL支持的每种搜索查询类型都有一个QueryBuilder。
MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("user", "kimchy");
/*
创建之后,QueryBuilder对象将提供一些方法来配置其创建的搜索查询的选项:
对匹配查询启用模糊匹配
在匹配查询中设置前缀长度选项
设置最大扩展选项以控制查询的模糊过程
*/
matchQueryBuilder.fuzziness(Fuzziness.AUTO);
matchQueryBuilder.prefixLength(3);
matchQueryBuilder.maxExpansions(10);
1.3 QueryBuilders工具类
// QueryBuilder对象也可以使用QueryBuilders实用工具类创建。此类提供了一些辅助方法,可以使用流畅的编程样式来创建QueryBuilder对象:
QueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("user", "kimchy")
.fuzziness(Fuzziness.AUTO)
.prefixLength(3)
.maxExpansions(10);
// 无论使用什么方法创建它,都必须将QueryBuilder对象添加到SearchSourceBuilder中,如下所示:
searchSourceBuilder.query(matchQueryBuilder);
1.4 sort 指定排序
- SearchSourceBuilder允许添加一个或多个SortBuilder实例。有四个特殊的实现(Field-,Score-,GeoDistance-和ScriptSortBuilder)。
// 按_score降序排列(默认)
sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC));
// 也按_id字段升序排列
sourceBuilder.sort(new FieldSortBuilder("id").order(SortOrder.ASC));
1.5 source
过滤
// 默认情况下,搜索请求返回文档_source的内容,但是像在Rest API中一样,您可以覆盖此行为。例如,您可以完全关闭_source检索:
sourceBuilder.fetchSource(false);
// 该方法还接受一个或多个通配符模式的数组,以控制以更细粒度的方式包含或排除哪些字段:
String[] includeFields = new String[] {"title", "innerObject.*"};
String[] excludeFields = new String[] {"user"};
sourceBuilder.fetchSource(includeFields, excludeFields);
1.6 highlight 高亮
// 可以通过在SearchSourceBuilder上设置HighlightBuilder来突出显示搜索结果。
// 通过将一个或多个HighlightBuilder.Field实例添加到HighlightBuilder中,可以为每个字段定义不同的突出显示行为。
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
HighlightBuilder highlightBuilder = new HighlightBuilder();
HighlightBuilder.Field highlightTitle =
new HighlightBuilder.Field("title"); // 为标题字段创建字段高亮
highlightTitle.highlighterType("unified"); // 为标题字段创建字段高亮
highlightBuilder.field(highlightTitle); // 将字段突出显示器添加到突出显示生成器
HighlightBuilder.Field highlightUser = new HighlightBuilder.Field("user");
highlightBuilder.field(highlightUser);
searchSourceBuilder.highlighter(highlightBuilder);
2. 聚合 Requesting Aggregations
// 可以通过首先创建适当的AggregationBuilder,然后在SearchSourceBuilder上进行设置,将聚合添加到搜索中
// 我们在公司名称上创建术语聚合,在公司员工平均年龄上进行子聚合:
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
TermsAggregationBuilder aggregation = AggregationBuilders.terms("by_company")
.field("company.keyword");
// subAggregation 子聚合
aggregation.subAggregation(AggregationBuilders.avg("average_age")
.field("age"));
searchSourceBuilder.aggregation(aggregation);
3. 建议 Requesting Suggestions
建议参考文档观看:Elasticsearch搜索Suggest功能优化
// 为user和文本kmichy创建一个新的TermSuggestionBuilder
// 添加建议生成器并将其命名为suggest_user
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
SuggestionBuilder termSuggestionBuilder =
SuggestBuilders.termSuggestion("user").text("kmichy");
SuggestBuilder suggestBuilder = new SuggestBuilder();
suggestBuilder.addSuggestion("suggest_user", termSuggestionBuilder);
searchSourceBuilder.suggest(suggestBuilder);
POST _search
{
"suggest": {
"suggest_user" : {
"text" : "kmichy",
"term" : {
"field" : "user"
}
}
}
}
4. 执行
4.1 Synchronous execution 同步
// 当以以下方式执行SearchRequest时,客户端在继续执行代码之前,等待SearchResponse返回:
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
// 如果无法在高级REST客户端中解析REST响应,请求超时或类似的情况,即服务器没有返回响应,则同步调用可能会引发IOException。
4.2 Asynchronous execution 异步
// 也可以以异步方式执行SearchRequest,以便客户端可以直接返回。
// 用户需要通过将请求和侦听器传递给异步搜索方法来指定如何处理响应或潜在的失败:
client.searchAsync(searchRequest, RequestOptions.DEFAULT, listener);
ActionListener<SearchResponse> listener = new ActionListener<SearchResponse>() {
@Override
public void onResponse(SearchResponse searchResponse) {
}
@Override
public void onFailure(Exception e) {
}
};
5. SearchResponse 返回
- 通过执行搜索返回的SearchResponse提供有关搜索执行本身以及对返回的文档的访问的详细信息。首先,有关于请求执行本身的有用信息,例如HTTP状态代码,执行时间或请求是提前终止还是超时:
RestStatus status = searchResponse.status();
TimeValue took = searchResponse.getTook();
Boolean terminatedEarly = searchResponse.isTerminatedEarly();
boolean timedOut = searchResponse.isTimedOut();
- 其次,响应还提供有关受搜索影响的分片总数以及成功与不成功分片的统计信息,从而提供有关分片级别执行的信息。也可以通过遍历ShardSearchFailures的数组来处理可能的故障,如以下示例所示:
int totalShards = searchResponse.getTotalShards();
int successfulShards = searchResponse.getSuccessfulShards();
int failedShards = searchResponse.getFailedShards();
for (ShardSearchFailure failure : searchResponse.getShardFailures()) {
// failures should be handled here
}
5.1 Retrieving SearchHits 命中信息
SearchHits hits = searchResponse.getHits();
// SearchHits提供有关所有命中的全局信息,例如命中总数或最高得分:
TotalHits totalHits = hits.getTotalHits();
// the total number of hits, must be interpreted in the context of totalHits.relation
long numHits = totalHits.value;
// whether the number of hits is accurate (EQUAL_TO) or a lower bound of the total (GREATER_THAN_OR_EQUAL_TO)
TotalHits.Relation relation = totalHits.relation;
float maxScore = hits.getMaxScore();
- 文档信息:
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
// do something with the SearchHit
}
- SearchHit提供对基本信息的访问,例如索引,文档ID和每个搜索命中的分数:
String index = hit.getIndex();
String id = hit.getId();
float score = hit.getScore();
- 此外,它使您可以以简单的JSON-String或键/值对的映射的形式获取文档源。在此映射中,常规字段由字段名称键入并包含字段值。多值字段以对象列表的形式返回,嵌套对象以另一个键/值映射的形式返回。这些情况需要相应地强制转换:
String sourceAsString = hit.getSourceAsString();
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String documentTitle = (String) sourceAsMap.get("title");
List<Object> users = (List<Object>) sourceAsMap.get("user");
Map<String, Object> innerObject =
(Map<String, Object>) sourceAsMap.get("innerObject");
5.2 Retrieving Highlighting 检索高亮
- 如果需要,可以从结果中的每个SearchHit中检索突出显示的文本片段。命中对象提供对到HighlightField实例的字段名称映射的访问,每个实例都包含一个或多个突出显示的文本片段:
SearchHits hits = searchResponse.getHits();
for (SearchHit hit : hits.getHits()) {
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
HighlightField highlight = highlightFields.get("title");
Text[] fragments = highlight.fragments();
String fragmentString = fragments[0].string();
}
5.3 Retrieving Aggregations 检索集合
- 检索集合 可以从SearchResponse中检索聚合,方法是先获取聚合树的根节点Aggregations对象,然后按名称获取聚合。
// 获取by_company条款汇总 获取用Elastic锁定的存储桶 从该存储桶中获取average_age子聚合
Aggregations aggregations = searchResponse.getAggregations();
Terms byCompanyAggregation = aggregations.get("by_company");
Bucket elasticBucket = byCompanyAggregation.getBucketByKey("Elastic");
Avg averageAge = elasticBucket.getAggregations().get("average_age");
double avg = averageAge.getValue();
// 请注意,如果按名称访问聚合,则需要根据请求的聚合类型指定聚合接口,否则将抛出ClassCastException:
Range range = aggregations.get("by_company");
// 这将引发异常,因为“ by_company”是一个术语聚合,但是我们尝试将其作为范围聚合来检索
5.4 Retrieving Suggestions 检索建议
- 要从SearchResponse中获取建议,请使用“建议”对象作为入口点,然后检索嵌套的建议对象:
//使用建议类访问建议 可以按名称检索建议。
Suggest suggest = searchResponse.getSuggest();
//您需要将它们分配给正确的类型的Recommendations类(此处为TermSuggestion),否则将引发ClassCastException
TermSuggestion termSuggestion = suggest.getSuggestion("suggest_user");
// 遍历建议条目 遍历一个条目中的选项
for (TermSuggestion.Entry entry : termSuggestion.getEntries()) {
for (TermSuggestion.Entry.Option option : entry) {
String suggestText = option.getText().string();
}
}
6. 建议Java 操作
自定义分词器:自定义分词实现搜索建议
GET /dddd/news/_search
{
"suggest": {
"title_suggest": {
"text": "2",
"completion": {
"field": "title.suggest",
"analyzer": "simple"
}
}
}
}
---------------------------------------
private static void searchSuggest(RestHighLevelClient highLevelClient,String index,String type,String tmptitle){
try {
SearchRequest searchRequest = new SearchRequest(index);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
CompletionSuggestionBuilder completionSuggestionBuilder = SuggestBuilders.completionSuggestion("title.suggest");
completionSuggestionBuilder.prefix(tmptitle).size(10);
SuggestBuilder suggestBuilder = new SuggestBuilder();
suggestBuilder.addSuggestion("title_suggest", completionSuggestionBuilder);
searchSourceBuilder.suggest(suggestBuilder);
searchSourceBuilder.query(QueryBuilders.matchQuery("content","2017"));
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
LOG.info("response---:{}",searchResponse.toString());
SearchHits hits = searchResponse.getHits();
Suggest suggest = searchResponse.getSuggest();
CompletionSuggestion completionSuggestion = suggest.getSuggestion("title_suggest");
//处理结果
//用来处理的接受结果
List<String> result = new ArrayList<>();
for(CompletionSuggestion.Entry op: completionSuggestion.getEntries()){
for(CompletionSuggestion.Entry.Option pp : op){
result.add(pp.getText().toString());
}
}
System.out.println(result.toString());
// SearchHits提供有关所有命中的全局信息,例如命中总数或最高得分:
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
String sourceAsString = hit.getSourceAsString();
LOG.info("sourceAsString --{}",sourceAsString);
}
} catch (Exception e) {
e.printStackTrace();
}
}