前提:1.导入RestHighLevelClient依赖
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>
2.将RestHighLevelClient Bean对象装配进spring容器
@Configuration
public class RestHighLevelClientConfig {
@Bean
public RestHighLevelClient restHighLevelClient() {
//192.168.115.131:9200是es的ip和端口
return new RestHighLevelClient(RestClient.builder(HttpHost.create(192.168.115.131:9200)));
}
}
一个基于es分布式搜索引擎的酒店搜索功能(包含复合查询,搜索字段高亮显示,指定排序,相关性算分查询[广告效果])
@Autowired
private RestHighLevelClient client;
//利用es搜索酒店信息功能
public PageResult<HotelDoc> queryList(RequestParams params) {
SearchRequest request = new SearchRequest(ESconstant.HOTEL_INDEX);
//封装查询条件
getBoolQueryBuilder(params, request);
//分页
Integer size = params.getSize();
Integer page = params.getPage();
request.source().from((page - 1) * size).size(size);
//指定排序(按照价格或者评论)
String sortBy = params.getSortBy();
if (!sortBy.equals("default")) {
request.source().sort(sortBy, SortOrder.DESC);
}
String location = params.getLocation();
//按照距离排序
if (location != null) {
request.source().sort(SortBuilders.geoDistanceSort("location", new GeoPoint(location)).order(SortOrder.ASC).unit(DistanceUnit.KILOMETERS));
}
SearchResponse response = null;
try {
//发出查询请求
response = client.search(request, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
//解析响应结果
return getHotelDocPageResult(response);
}
//解析响应结果封装方法
private PageResult<HotelDoc> getHotelDocPageResult(SearchResponse response) {
ArrayList<HotelDoc> hotelDocs = new ArrayList<>();
SearchHits responseHits = response.getHits();
long value = responseHits.getTotalHits().value;
for (SearchHit hit : responseHits.getHits()) {
HotelDoc hotelDoc = JSON.parseObject(hit.getSourceAsString(), HotelDoc.class);
Object[] sortValues = hit.getSortValues();
if (sortValues.length > 0) {
Object sortValue = sortValues[sortValues.length - 1];
hotelDoc.setDistance(sortValue);
}
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
if (!CollectionUtils.isEmpty(highlightFields)) {
// 根据字段名获取高亮结果
HighlightField highlightField = highlightFields.get("name");
if (highlightField != null) {
// 获取高亮值
String name = highlightField.getFragments()[0].string();
// 覆盖非高亮结果
hotelDoc.setName(name);
}
}
hotelDocs.add(hotelDoc);
}
PageResult<HotelDoc> result = new PageResult<>();
result.setHotels(hotelDocs);
result.setTotal(value);
return result;
}
//复合查询,编写查询条件
private void getBoolQueryBuilder(RequestParams params, SearchRequest request) {
String key = params.getKey();
String brand = params.getBrand();
String city = params.getCity();
String starName = params.getStarName();
Integer minPrice = params.getMinPrice();
Integer maxPrice = params.getMaxPrice();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
if (key == null || "".equals(key)) {
boolQuery.must(QueryBuilders.matchAllQuery());
} else {
boolQuery.must(QueryBuilders.matchQuery("all", key));
}
// 高亮搜索字段
request.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false));
if (brand != null && !"".equals(brand)) {
boolQuery.filter(QueryBuilders.termQuery("brand", brand));
}
if (city != null && !"".equals(city)) {
boolQuery.filter(QueryBuilders.termQuery("city", city));
}
if (starName != null && !"".equals(starName)) {
boolQuery.filter(QueryBuilders.termQuery("starName", starName));
}
if (maxPrice != null && !"".equals(maxPrice)) {
boolQuery.filter(QueryBuilders.rangeQuery("price").lte(maxPrice).gte(minPrice));
}
//当指定排序时,_score为null,不能为_score加分,相关性算分无作用
FunctionScoreQueryBuilder functionScoreQuery =
QueryBuilders.functionScoreQuery(
// 原始查询,相关性算分的查询
boolQuery,
// function score的数组
new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{
// 其中的一个function score 元素
new FunctionScoreQueryBuilder.FilterFunctionBuilder(
// 过滤条件
QueryBuilders.termQuery("isAD", true),
// 算分函数
ScoreFunctionBuilders.weightFactorFunction(10)
)
});
//设置查询条件DSL
request.source().query(functionScoreQuery);
}
根据品牌,星级,城市进行聚合查询功能
@Override
public Map<String, List<String>> getFilters(RequestParams params) {
Map<String, List<String>> map = new HashMap<>();
SearchRequest request = new SearchRequest(ESconstant.HOTEL_INDEX);
getBoolQueryBuilder(params, request);
request.source().size(0);
request.source().aggregation(AggregationBuilders.terms("brandAgg").field("brand").size(100));
request.source().aggregation(AggregationBuilders.terms("starAgg").field("starName").size(100));
request.source().aggregation(AggregationBuilders.terms("cityAgg").field("city").size(100));
SearchResponse response = null;
try {
response = client.search(request, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
Aggregations aggregations = response.getAggregations();
List<String> brandAgg = getAggByName(aggregations, "brandAgg");
map.put("brand", brandAgg);
List<String> starAgg = getAggByName(aggregations, "starAgg");
map.put("starName", starAgg);
List<String> cityAgg = getAggByName(aggregations, "cityAgg");
map.put("city", cityAgg);
return map;
}
//根据聚合名称获取聚合结果
private List<String> getAggByName(Aggregations aggregations, String aggName) {
// 4.1.根据聚合名称获取聚合结果
Terms brandTerms = aggregations.get(aggName);
// 4.2.获取buckets
List<? extends Terms.Bucket> buckets = brandTerms.getBuckets();
// 4.3.遍历
List<String> brandList = new ArrayList<>();
for (Terms.Bucket bucket : buckets) {
// 4.4.获取key
String key = bucket.getKeyAsString();
brandList.add(key);
}
return brandList;
}
//根据自定义分词自动补全搜索条件
@Override
public List<String> getSuggestions(String prefix) {
try {
// 1.准备Request
SearchRequest request = new SearchRequest("hotel");
// 2.准备DSL
request.source().suggest(new SuggestBuilder().addSuggestion(
"suggestions",
SuggestBuilders.completionSuggestion("suggestion")
.prefix(prefix)
.skipDuplicates(true)
.size(10)
));
// 3.发起请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 4.解析结果
Suggest suggest = response.getSuggest();
// 4.1.根据补全查询名称,获取补全结果
CompletionSuggestion suggestions = suggest.getSuggestion("suggestions");
// 4.2.获取options
List<CompletionSuggestion.Entry.Option> options = suggestions.getOptions();
// 4.3.遍历
List<String> list = new ArrayList<>(options.size());
for (CompletionSuggestion.Entry.Option option : options) {
String text = option.getText().toString();
list.add(text);
}
return list;
} catch (IOException e) {
throw new RuntimeException(e);
}
}