ElasticSearch High Level REST API(2)搜索查询
基本搜索
在search搜索中大部分的搜索条件添加都可通过设置SearchSourceBuilder来实现。如下为一段带有分页的简单搜索查询示例
@GetMapping("/search/base")
public String searchBase() {
SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.termQuery("name.keyword", "Joe.Ye"));
sourceBuilder.from(0);
sourceBuilder.size(5);
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS)); //设置一个可选的超时,控制允许搜索的时间
searchRequest.source(sourceBuilder);
try {
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
Long total = searchResponse.getHits().getTotalHits().value; //获取匹配的总数量
System.out.println("总记录数: " + total);
for (SearchHit hit : searchResponse.getHits().getHits()) {
float score = hit.getScore(); //获得分数,即匹配度
String source = hit.getSourceAsString();
log.info("score: {}, source: {}", score, source);
}
//client.close();
return JSON.toJSONString(searchResponse);
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
Status: 200
总记录数: 4
score: 0.6931472, source: {"age":28,"height":175.2,"name":"Joe.Ye"}
score: 0.5389965, source: {"name":"Joe.Ye","email":"yezhou@yezhou.org","homepage":"http://www.appblog.cn"}
score: 0.5389965, source: {"name":"Joe.Ye","age":28,"homepage":"http://www.appblog.cn"}
score: 0.5389965, source: {"name":"Joe.Ye","email":"yezhou@yezhou.org","homepage":"http://www.appblog.cn"}
search查询的返回值为SearchResponse
,调用SearchResponse
的getHits()
方法会获取SearchHits
对象,然后再通过SearchHits
的getHits()
方法即返回一个SearchHit[]
数组。
遍历SearchHit[]
数组获取每一个对象,通过hit.getScore()
可获取分数,即搜索匹配度。通过hit.getSourceAsString()
可得到对象的json字符串。
备注:在上述查询中用到了termQuery查询,ES还提供了matchQuery查询,不同的查询需求中需要选择不同的查询,在此需要了解这两个查询的区别:
termQuery
: term为不使用分词器查找,类似精确查找。
matchQuery
: mactch为使用分词器进行查找,会查询到一些近似匹配的内容。
SearchHit使用汇总
要获取返回的内容,需要获得SearchHit,下面总结下SearchHit的一些使用:
SearchHits hits = searchResponse.getHits();
long totalHits = hits.getTotalHits().value; //查询命中总数
float maxScore = hits.getMaxScore(); //查询命中的最高分数
//SearchHits遍历
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
}
//通过SearchHit还可以获取返回数据的索引、类型、docId和得分等基本信息
String index = hit.getIndex();
String type = hit.getType();
String id = hit.getId();
float score = hit.getScore();
//hit还可以以Json字符串或Map的形式返回数据
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");
指定排序
排序有两种排序方式,第一通过ScoreSortBuilder
实现按分数(即匹配度)排序;第二种方式通过指定字段来排序,如通过_uid
字段排序
sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC)); //按分数(即匹配度)排序
sourceBuilder.sort(new FieldSortBuilder("_uid").order(SortOrder.ASC)); //通过指定字段来排序
关闭检索
有时我们只想要知道到底匹配了多少条记录,但不关系具体每条记录的内容,这个时候我们可以选择关闭检索,不去查询每天数据的内容,可通过如下方式实现:
sourceBuilder.fetchSource(false);
关闭检索后,只返回总记录数,遍历输出每条数据均为 null
另外还可以通过SourceBuilder
接受一个或多个数组,来控制需要返回哪些字段,排除哪些字段。具体实现如下,第一个数组参数为要接受的字段,第二个数组参数为要排除的内容:
String[] includeFields = new String[] {"title", "user", "innerObject.*"};
String[] excludeFields = new String[] {"_type"};
sourceBuilder.fetchSource(includeFields, excludeFields);
高亮显示
通过向SearchSourceBuilder
添加HighlightBuilder
示例可添加高亮显示功能
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
HighlightBuilder highlightBuilder = new HighlightBuilder();
HighlightBuilder.Field highlightTitle = new HighlightBuilder.Field("title");
highlightTitle.highlighterType("unified"); //字段高亮显示类型,默认用标签包裹高亮字词
highlightBuilder.field(highlightTitle);
searchSourceBuilder.highlighter(highlightBuilder);
以上只是在查询中加入高亮显示的功能,那么我们如何在查询结果中获取呢,通过SearchHit
的getHighlightFields()
方法获取我们需要关键内容:
SearchHits hits = searchResponse.getHits();
for (SearchHit hit : hits.getHits()) {
Map highlightFields = hit.getHighlightFields();
HighlightField highlight = highlightFields.get("title");
Text[] fragments = highlight.fragments();
String fragmentString = fragments[0].string();
}
聚合操作
获取平均值聚合示例,最大值、最小值、求和类似
@GetMapping("search/aggregation")
public void aggregation() {
RestHighLevelClient client = elasticClient.getRestHighLevelClient();
SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
TermsAggregationBuilder aggregation = AggregationBuilders.terms("by_sex")
.field("sex.keyword"); //若不加keyword,在text类型上进行聚合操作时会报错
aggregation.subAggregation(AggregationBuilders.avg("avg_age")
.field("age")); //avg_age 为子聚合名称,名称可随意
searchSourceBuilder.aggregation(aggregation);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = null;
try {
searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
Aggregations aggregations = searchResponse.getAggregations();
Terms bySexAggregation = aggregations.get("by_sex");
Terms.Bucket elasticBucket = bySexAggregation.getBucketByKey("女性");
Avg averageAge = elasticBucket.getAggregations().get("avg_age");
double avg = averageAge.getValue();
System.out.println("女性平均年龄:" + avg);
}
Stats统计
@GetMapping("search/stats")
public void stats() {
RestHighLevelClient client = elasticClient.getRestHighLevelClient();
SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
TermsAggregationBuilder aggregation = AggregationBuilders.terms("by_sex")
.field("sex.keyword"); //by_sex为聚合名称,名称可随意
aggregation.subAggregation(AggregationBuilders.stats("stat_age")
.field("age")); //avg_age 为子聚合名称,名称可随意
searchSourceBuilder.aggregation(aggregation);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = null;
try {
searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
Aggregations aggregations = searchResponse.getAggregations();
Terms bySexAggregation = aggregations.get("by_sex");
List<? extends Terms.Bucket> buckets = bySexAggregation.getBuckets();
for (Terms.Bucket bucket : buckets) {
Stats statAge = bucket.getAggregations().get("stat_age");
System.out.println(bucket.getKey()); //获取分组名称
System.out.println("平均值:" + statAge.getAvg());
System.out.println("总数:" + statAge.getSum());
System.out.println("最大值:" + statAge.getMaxAsString());
System.out.println("最小值:" + statAge.getMin());
}
}
版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/03/19/elasticsearch-high-level-rest-api-search-query/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。
共有 0 条评论