赞
踩
主要参照官方文档(英文版):https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.6/java-rest-high-search.html
下边是我的学习,并进行翻译,我会对文档进行适当的修改,达到更容易理解的目的,案例仍然用官网的。
该SearchRequest
用于具有与搜索文件,汇总,建议做,也要求提供高亮显示所产生的文件的方式中的任何操作。
ES 的查询,在使用 REST Client 操作起来并不像我们之前对关系型数据库,写sql来操作(我之前持久层习惯使用SpringDateJPA ,简单的查询通过方法名就可以构造出来了,复杂的查询则通过sql来,这样很方便,不用专门构建查询的对象)。而这里需要我们通过构造查询条件来完成。所有的操作都通过操作对象的方式来操作ES
# # 以最基本的形式,我们可以构造查询:
- SearchRequest searchRequest = new SearchRequest();
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
- searchSourceBuilder.query(QueryBuilders.matchAllQuery());
- searchRequest.source(searchSourceBuilder);
熟悉关系型数据库的sql的,可以看一下 ,其实,这里 SearchRequest 对象就相当于是 select如果想要添加查询条件,则都是找对应的 SearchBuilder 来完成。看到上边的类似于XXXBuilder不要慌。
# # 我们首先来看一下一些可选参数SearchRequest
:
SearchRequest searchRequest = new SearchRequest("posts");
| 将请求限制为索引 |
还有两个其他有趣的可选参数:
searchRequest.routing("routing");
| 设置路由参数 |
searchRequest.indicesOptions(IndicesOptions.lenientExpandOpen());
| 设置 |
searchRequest.preference("_local");
| 使用首选项参数,例如,执行搜索以偏爱本地碎片。默认设置是随机分片。 |
# # SearchSourceBuilder (通过这个添加查询条件)
前边提到过,都是通过XXXBuilder来添加额外的条件的。
以下是一些常见选项的示例:
- SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
- sourceBuilder.query(QueryBuilders.termQuery("user", "kimchy"));
- sourceBuilder.from(0);
- sourceBuilder.size(5);
- sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
|
|
| 设置查询。可以是任何类型 |
| 设置 |
| 设置 |
| 设置一个可选的超时时间,以控制允许搜索的时间。 |
在此之后,SearchSourceBuilder
只需要将添加到 SearchRequest
:
- SearchRequest searchRequest = new SearchRequest();
- searchRequest.indices("posts");
- searchRequest.source(sourceBuilder);
# # MatchQueryBuilder
搜索查询是使用QueryBuilder
对象创建的。一个QueryBuilder
存在通过Elasticsearch支持的每一个搜索查询类型查询DSL。
QueryBuilder
可以使用其构造函数创建一个:
MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("user", "kimchy");
| 这个其实就是:where user="kimchy" |
创建QueryBuilder
对象后,该对象将提供方法来配置其创建的搜索查询的选项:
- matchQueryBuilder.fuzziness(Fuzziness.AUTO);
- matchQueryBuilder.prefixLength(3);
- matchQueryBuilder.maxExpansions(10);
| 对匹配查询启用模糊匹配 |
| 在匹配查询中设置前缀长度选项 |
| 设置最大扩展选项以控制查询的模糊过程 |
QueryBuilder
也可以使用QueryBuilders
实用程序类创建对象。此类提供了一些辅助方法,可以QueryBuilder
使用流畅的编程样式来创建对象:
- QueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("user", "kimchy")
- .fuzziness(Fuzziness.AUTO)
- .prefixLength(3)
- .maxExpansions(10);
无论用于创建它的方法是什么,都QueryBuilder
必须将对象添加到SearchSourceBuilder
,如下所示:
searchSourceBuilder.query(matchQueryBuilder);
https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.6/java-rest-high-query-builders.html 提供了所有可用搜索查询的列表以及它们的相应QueryBuilder
对象和QueryBuilders
帮助方法。
# # 添加排序
在SearchSourceBuilder
允许添加一个或多个SortBuilder
实例。有四个特殊的实现(Field-,Score-,GeoDistance-和ScriptSortBuilder)。
- sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC));
- sourceBuilder.sort(new FieldSortBuilder("id").order(SortOrder.ASC));
| 根据打分降序排列(默认) |
| 也按 |
默认情况下,搜索请求返回文档的内容,_source
但是就像在Rest API中一样,您可以覆盖此行为。例如,您可以_source
完全关闭检索:
sourceBuilder.fetchSource(false);
该方法还接受一个或多个通配符模式的数组,以控制以更细粒度的方式包含或排除哪些字段:
- String[] includeFields = new String[] {"title", "innerObject.*"};
- String[] excludeFields = new String[] {"user"};
- sourceBuilder.fetchSource(includeFields, excludeFields);
# # 高亮显示
突出显示搜索结果可以通过设置来实现HighlightBuilder
的 SearchSourceBuilder
。通过向中添加一个或多个HighlightBuilder.Field
实例,可以为每个字段定义不同的突出显示行为HighlightBuilder
。
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
- HighlightBuilder highlightBuilder = new HighlightBuilder();
- //添加高亮显示的字段
- HighlightBuilder.Field highlightTitle =
- new HighlightBuilder.Field("title");
- //指定高亮的类型
- highlightTitle.highlighterType("unified");
- //将高亮的相关配置告诉Builder
- highlightBuilder.field(highlightTitle);
- //新加一个高亮显示的字段
- HighlightBuilder.Field highlightUser = new HighlightBuilder.Field("user");
- highlightBuilder.field(highlightUser);
- //将高亮的相关配置告诉上级Builder
- searchSourceBuilder.highlighter(highlightBuilder);
Rest API文档中有许多选项的详细说明。Rest API参数(例如pre_tags
)通常由具有相似名称(例如#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);
Building Aggregations 页面提供了所有可用聚合及其相应AggregationBuilder
对象和AggregationBuilders
帮助器方法的列表。
后面我们将看到如何来访问聚合的SearchResponse
。
# # Requesting Suggestions
要将“Suggestions”添加到搜索请求中,请使用SuggestionBuilder
可从SuggestBuilders
工厂类轻松访问的实现之一。建议使用者需要添加到顶层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);
|
|
| 添加建议生成器并命名 |
想要使用 聚合(aggregations),就必须指定下边的为true
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
- searchSourceBuilder.profile(true);
# # 返回结果(同步情况下)
当SearchRequest
以以下方式执行时,客户端将等待SearchResponse
返回,然后继续执行代码:
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
IOException
如果无法在 high-level REST client 中解析REST响应,请求超时或类似的情况(如果服务器没有响应返回),则同步调用可能会引发错误。
在服务器返回4xx
或5xx
错误代码的情况下,高级客户端尝试改为解析响应正文错误详细信息,然后引发泛型ElasticsearchException
并将原始的ResponseException
作为抑制的异常添加到它。
执行 SearchRequest
也可以异步方式完成,以便客户端可以直接返回。用户需要通过将请求和侦听器传递给异步搜索方法来指定如何处理响应或潜在的失败:
client.searchAsync(searchRequest, RequestOptions.DEFAULT, listener);
| 的 |
异步方法不会阻塞并立即返回。完成ActionListener
后,onResponse
如果执行成功完成,则使用onFailure
方法进行调用;如果执行失败,则使用方法进行调用。故障情况和预期的异常与同步执行情况相同。
典型的侦听器search
如下所示:
- ActionListener<SearchResponse> listener = new ActionListener<SearchResponse>() {
- @Override
- public void onResponse(SearchResponse searchResponse) {
- //成功后执行的内容
-
- }
-
- @Override
- public void onFailure(Exception e) {
- //失败后执行的内容
- }
- };
# # 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
提供所有点击全局信息,比如命中总数或最大比分:
- 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();
嵌套在中的SearchHits
是可以迭代的各个搜索结果:
- 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");
如果需要,可以从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();
- }
# # 检索聚合
可以从检索聚合,方法是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();
| 获取 |
| 获取带有密钥的存储桶 |
|
|
请注意,如果按名称访问聚合,则需要根据请求的聚合类型指定聚合接口,否则ClassCastException
将抛出:
Range range = aggregations.get("by_company");
| 这将引发异常,因为“ by_company”是一个 |
也可以将所有聚合作为以聚合名称作为关键字的映射来访问。在这种情况下,必须明确地强制转换为正确的聚合接口:
- 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();
- }
- }
-
-
-
-
-
要从中获取建议SearchResponse
,请使用Suggest
对象作为入口点,然后检索嵌套的建议对象:
- 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();
- }
- }
# # 检索分析结果
SearchResponse
使用getProfileResults()
方法从中检索分析结果。该方法为执行中涉及的每个分片返回一个Map
包含一个ProfileShardResult
对象的对象 SearchRequest
。使用唯一地标识配置文件结果所对应的分片的密钥ProfileShardResult
存储在其中Map
。
以下示例代码显示了如何迭代每个分片的所有分析结果:
- Map<String, ProfileShardResult> profilingResults =
- searchResponse.getProfileResults();
- for (Map.Entry<String, ProfileShardResult> profilingResult : profilingResults.entrySet()) {
- String key = profilingResult.getKey();
- ProfileShardResult profileShardResult = profilingResult.getValue();
- }
| 检索 |
| 如果知道密钥,则可以通过分片的密钥来检索分析结果,否则,对所有分析结果进行迭代可能会更简单 |
| 检索标识 |
| 检索 |
所述ProfileShardResult
对象本身包含一个或多个查询简档的结果,一个用于抵靠底层Lucene索引执行的每个查询:
- List<QueryProfileShardResult> queryProfileShardResults =
- profileShardResult.getQueryProfileResults();
- for (QueryProfileShardResult queryProfileResult : queryProfileShardResults) {
-
- }
| 检索列表 |
| 遍历每个 |
每个都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();
- }
| 检索 |
| 遍历聚合配置文件结果 |
| 检索聚合的类型(与用于执行聚合的Java类相对应) |
| 检索执行Lucene收集器所花费的毫秒数 |
| 检索子聚合的概要文件结果(如果有) |
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。