Elasticsearch Java High Level REST Client(Search API)

Search API

搜索请求

SearchRequest用于与搜索文档、聚合、suggestions相关的任何操做,还提供了在结果文档上请求高亮的方法。编程

在最基本的表单中,咱们能够向请求添加查询:segmentfault

SearchRequest searchRequest = new SearchRequest(); 
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); 
searchSourceBuilder.query(QueryBuilders.matchAllQuery()); 
searchRequest.source(searchSourceBuilder);
  • 建立SeachRequest,没有参数,这将针对全部索引运行。
  • 大多数搜索参数都添加到SearchSourceBuilder中,它为搜索请求body中的全部内容提供了setter。
  • match_all查询添加到SearchSourceBuilder
  • SearchSourceBuilder添加到SeachRequest

可选参数

咱们先来看一下SearchRequest的一些可选参数:数组

SearchRequest searchRequest = new SearchRequest("posts");
searchRequest.types("doc");
  • 将请求限制为一个索引。
  • 将请求限制为一个类型。

还有一些其余有趣的可选参数:异步

searchRequest.routing("routing");
  • 设置路由参数。
searchRequest.indicesOptions(IndicesOptions.lenientExpandOpen());
  • 设置IndicesOptions控制如何解析不可用的索引以及如何扩展通配符表达式。
searchRequest.preference("_local");
  • 使用首选项参数,例如执行搜索以优先选择本地碎片,默认是随机的跨碎片。

使用SearchSourceBuilder

控制搜索行为的大多数选项均可以在SearchSourceBuilder上设置,它包含或多或少与Rest API的搜索请求body中等效的选项。ide

如下是一些常见选项的几个示例:函数

SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); 
sourceBuilder.query(QueryBuilders.termQuery("user", "kimchy")); 
sourceBuilder.from(0); 
sourceBuilder.size(5); 
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
  • 使用默认选项建立SearchSourceBuilder
  • 设置查询,能够是任何类型的QueryBuilder
  • 设置肯定结果要从哪一个索引开始搜索的from选项,默认为0
  • 设置肯定搜索命中返回的数的size选项,默认为10
  • 设置一个可选的超时,控制容许搜索的时间。

在此以后,只需将SearchSourceBuilder添加到SearchRequestpost

SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("posts");
searchRequest.source(sourceBuilder);

构建查询

使用QueryBuilder对象建立搜索查询,QueryBuilder存在对于Elasticsearch的查询DSL支持的每种搜索查询类型。性能

可使用其构造函数建立QueryBuilderfetch

MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("user", "kimchy");
  • 建立一个在字段“user”上匹配文本“kimchy”的全文匹配查询

建立后,QueryBuilder对象提供了配置其建立的搜索查询选项的方法:ui

matchQueryBuilder.fuzziness(Fuzziness.AUTO); 
matchQueryBuilder.prefixLength(3); 
matchQueryBuilder.maxExpansions(10);
  • 在匹配查询上启用模糊匹配。
  • 在匹配查询上设置前缀长度选项。
  • 设置最大扩展选项以控制查询的模糊过程。

也可使用QueryBuilders实用程序类建立QueryBuilder对象,此类提供了可用于使用流畅的编程样式建立QueryBuilder对象的辅助方法:

QueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("user", "kimchy")
                                                .fuzziness(Fuzziness.AUTO)
                                                .prefixLength(3)
                                                .maxExpansions(10);

不管用于建立它的方法是什么,都必须将QueryBuilder对象添加到SearchSourceBuilder,以下所示:

searchSourceBuilder.query(matchQueryBuilder);

构建查询页面提供了全部可用的搜索查询的列表及其相应的QueryBuilder对象和QueryBuilders辅助方法。

指定排序

SearchSourceBuilder容许添加一个或多个SortBuilder实例,有四种特殊的实现(Field-,Score-,GeoDistance-和ScriptSortBuilder)。

sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC)); 
sourceBuilder.sort(new FieldSortBuilder("_uid").order(SortOrder.ASC));
  • _score降序排序(默认值)。
  • 也能够按_id字段进行升序排序。

源过滤

默认状况下,搜索请求会返回文档_source的内容,但与Rest API中的内容同样,你能够覆盖此行为,例如,你能够彻底关闭_source检索:

sourceBuilder.fetchSource(false);

该方法还接受一个或多个通配符模式的数组,以控制以更精细的方式包含或排除哪些字段:

String[] includeFields = new String[] {"title", "user", "innerObject.*"};
String[] excludeFields = new String[] {"_type"};
sourceBuilder.fetchSource(includeFields, excludeFields);

请求高亮

经过在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);
  • 建立一个新的HighlightBuilder
  • title字段建立字段高光色。
  • 设置字段高光色类型。
  • 将字段高光色添加到高亮构建器。

Rest API文档中有许多选项须要详细说明,Rest API参数(例如pre_tags)一般由具备类似名称的setter更改而来(例如#preTags(String ...))。

稍后能够从SearchResponse中检索高亮的文本片断。

请求聚合

能够经过先建立适当的AggregationBuilder而后在SearchSourceBuilder上设置聚合来将聚合添加到搜索中,在如下示例中,咱们在公司名称上建立terms聚合 ,使用子聚合在公司员工平均年龄上:

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
TermsAggregationBuilder aggregation = AggregationBuilders.terms("by_company")
        .field("company.keyword");
aggregation.subAggregation(AggregationBuilders.avg("average_age")
        .field("age"));
searchSourceBuilder.aggregation(aggregation);

构建聚合页面提供了全部可用的聚合的列表及其对应的AggregationBuilder对象和AggregationBuilders辅助方法。

稍后咱们将看到如何访问SearchResponse中的聚合。

请求Suggestion

要向搜索请求添加建议,请使用从SuggestBuilders工厂类中可轻松访问的SuggestionBuilder的实现之一,Suggestion构建器须要添加到顶级SuggestBuilder,它自己能够在SearchSourceBuilder上设置。

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
SuggestionBuilder termSuggestionBuilder =
    SuggestBuilders.termSuggestion("user").text("kmichy"); 
SuggestBuilder suggestBuilder = new SuggestBuilder();
suggestBuilder.addSuggestion("suggest_user", termSuggestionBuilder); 
searchSourceBuilder.suggest(suggestBuilder);
  • user字段和文本kmichy建立一个新的TermSuggestionBuilder
  • 添加suggestion构建器并将其命名为suggest_user

咱们稍后将看到如何从SearchResponse中检索suggestion。

分析查询和聚合

分析API可用于分析特定搜索请求的查询和聚合的执行状况,为了使用它,必须在SearchSourceBuilder上将profile标志设置为true

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.profile(true);

执行SearchRequest后,相应的SearchResponse将包含分析结果。

同步执行

如下列方式执行SearchRequest时,客户端在继续执行代码以前等待返回SearchResponse

SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

异步执行

执行SearchRequest也能够以异步方式完成,以便客户端能够直接返回,用户须要经过将请求和监听器传递给异步搜索方法来指定响应或潜在的故障如何处理:

client.searchAsync(searchRequest, RequestOptions.DEFAULT, listener);
  • 要执行的SearchRequest和执行完成时要使用的ActionListener

异步方法不会阻塞而且当即返回,完成后,若是执行成功完成则使用onResponse方法回调ActionListener,若是失败则使用onFailure方法。

SearchResponse的典型监听器以下所示:

ActionListener<SearchResponse> listener = new ActionListener<SearchResponse>() {
    @Override
    public void onResponse(SearchResponse searchResponse) {
        
    }

    @Override
    public void onFailure(Exception e) {
        
    }
};
  • onResponse:执行成功完成时调用。
  • onFailure:在整个SearchRequest失败时调用。

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
}

检索SearchHits

要访问返回的文档,咱们须要先获取响应中包含的SearchHits

SearchHits hits = searchResponse.getHits();

SearchHits提供有关全部匹配的全局信息,例如总命中数或最高分数:

long totalHits = hits.getTotalHits();
float maxScore = hits.getMaxScore();

嵌套在SearchHits中的是能够迭代的单个搜索结果:

SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
    // do something with the SearchHit
}

SearchHit提供对每一个搜索命中的索引、类型、docId和分数等基本信息的访问:

String index = hit.getIndex();
String type = hit.getType();
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");

检索高亮

若是须要,能够从结果中的每一个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();
}
  • 获取title字段的高亮。
  • 获取包含高亮的字段内容的一个或多个片断。

检索聚合

能够从SearchResponse检索聚合,先获取聚合树的根,Aggregations对象,而后按名称获取聚合。

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();
  • 获取by_companyterms聚合。
  • 获取使用Elastic键入的桶。
  • 从该桶中获取average_age子聚合。

请注意,若是按名称访问聚合,则须要根据所请求的聚合类型指定聚合接口,不然将引起ClassCastException

Range range = aggregations.get("by_company");
  • 这将引起异常,由于“by_company”是一个terms聚合,但咱们尝试将其做为range聚合进行检索。

还能够将全部聚合做为由聚合名称键入的映射进行访问,在这种状况下,须要显式地进行到正确聚合接口的转换:

Map<String, Aggregation> aggregationMap = aggregations.getAsMap();
Terms companyAggregation = (Terms) aggregationMap.get("by_company");

还有一些getter将全部顶级聚合做为列表返回:

List<Aggregation> aggregationList = aggregations.asList();

最后但并不是最不重要的是,你能够迭代全部聚合,而后例如决定如何根据类型进一步处理它们:

for (Aggregation agg : aggregations) {
    String type = agg.getType();
    if (type.equals(TermsAggregationBuilder.NAME)) {
        Bucket elasticBucket = ((Terms) agg).getBucketByKey("Elastic");
        long numberOfDocs = elasticBucket.getDocCount();
    }
}

检索suggestions

要从SearchResponse获取suggestions,请使用Suggest对象做为入口点,而后检索嵌套的suggestion对象:

Suggest suggest = searchResponse.getSuggest(); 
TermSuggestion termSuggestion = suggest.getSuggestion("suggest_user"); 
for (TermSuggestion.Entry entry : termSuggestion.getEntries()) { 
    for (TermSuggestion.Entry.Option option : entry) { 
        String suggestText = option.getText().string();
    }
}
  • 使用Suggest类访问suggestions。
  • 能够经过名称检索suggestions,你须要将它们分配给正确类型的Suggestion类(此处为TermSuggestion),不然抛出ClassCastException
  • 迭代suggestion条目。
  • 在一个条目中迭代选项。

检索性能分析结果

使用getProfileResults()方法从SearchResponse检索分析结果,此方法返回包含SearchSquest执行中涉及的每一个碎片的ProfileShardResult对象的MapProfileShardResult使用惟一标识分析结果对应的碎片的键存储在Map中。

下面是一个示例代码,显示如何迭代每一个碎片的全部分析结果:

Map<String, ProfileShardResult> profilingResults =
        searchResponse.getProfileResults(); 
for (Map.Entry<String, ProfileShardResult> profilingResult : profilingResults.entrySet()) { 
    String key = profilingResult.getKey(); 
    ProfileShardResult profileShardResult = profilingResult.getValue(); 
}
  • SearchResponse中检索ProfileShardResultMap
  • 若是键已知,则能够经过碎片的键检索分析结果,不然迭代全部分析结果可能更简单。
  • 检索标识ProfileShardResult属于哪一个碎片的键。
  • 检索给定碎片的ProfileShardResult

ProfileShardResult对象自己包含一个或多个查询分析结果,每一个查询针对基础Lucene索引执行:

List<QueryProfileShardResult> queryProfileShardResults =
        profileShardResult.getQueryProfileResults(); 
for (QueryProfileShardResult queryProfileResult : queryProfileShardResults) { 

}
  • 检索QueryProfileShardResult的列表。
  • 迭代每一个QueryProfileShardResult

每一个QueryProfileShardResult都提供对详细查询树执行的访问,做为ProfileResult对象列表返回:

for (ProfileResult profileResult : queryProfileResult.getQueryResults()) { 
    String queryName = profileResult.getQueryName(); 
    long queryTimeInMillis = profileResult.getTime(); 
    List<ProfileResult> profiledChildren = profileResult.getProfiledChildren(); 
}
  • 迭代分析结果。
  • 检索Lucene查询的名称。
  • 检索执行Lucene查询所花费的时间。
  • 检索子查询的分析结果(若是有)。

Rest API文档包含有关分析查询的更多信息以及查询分析信息的说明。

QueryProfileShardResult还能够访问Lucene收集器的分析信息:

CollectorResult collectorResult = queryProfileResult.getCollectorResult();  
String collectorName = collectorResult.getName();  
Long collectorTimeInMillis = collectorResult.getTime(); 
List<CollectorResult> profiledChildren = collectorResult.getProfiledChildren();
  • 检索Lucene收集器的分析结果。
  • 检索Lucene收集器的名称。
  • 检索执行Lucene收集器所花费的时间。
  • 检索子收集器的分析结果(若是有)。

Rest API文档包含有关Lucene收集器的分析信息的更多信息。

以与查询树执行很是相似的方式,QueryProfileShardResult对象提供对详细聚合树执行的访问:

AggregationProfileShardResult aggsProfileResults =
        profileShardResult.getAggregationProfileResults(); 
for (ProfileResult profileResult : aggsProfileResults.getProfileResults()) { 
    String aggName = profileResult.getQueryName(); 
    long aggTimeInMillis = profileResult.getTime(); 
    List<ProfileResult> profiledChildren = profileResult.getProfiledChildren(); 
}
  • 检索AggregationProfileShardResult
  • 迭代聚合分析结果。
  • 检索聚合的类型(对应于用于执行聚合的Java类)。
  • 检索执行Lucene收集器所花费的时间。
  • 检索子聚合的分析结果(若是有)。

Rest API文档包含有关分析聚合的更多信息。

相关文章
相关标签/搜索