20 Rest高级客户端实践(六):搜索入门和基本API介绍


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();
解析
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值