/*
* @Copyright (c) 2021. 于吉利 All Rights Reserved
* @Author: 于吉利
* @Function:
* @Date: 2021/9/13 下午2:11
* @version:1.0
* @Changes:
* @Description:
*
*/
package com.huajun.search.service.impl;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.huajun.search.entity.Product;
import com.huajun.search.service.ISmartQuery;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.elasticsearch.common.text.Text;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Service
public class SmartQueryImpl implements ISmartQuery {
@Autowired
private RestHighLevelClient restHighLevelClient;
@Autowired
private ObjectMapper objectMapper;
@Override
public List<Product> searcher(String keyWords, String indexName, Integer pageNum, Integer pageSize) {
List<Product> productInfos = new ArrayList<Product>();
SearchRequest searchRequest;
if (indexName == "all") {
searchRequest = new SearchRequest(indexName);
} else {
searchRequest = new SearchRequest();////穿件SeachRequest,Without arguments this runs against all indices.
}
SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.searchSource();
//分页开始
//searchSourceBuilder.from(0).size(10);
//init
if (pageSize == null) {
pageSize = 10;
}
if (pageNum == null) {
pageNum = 1;
}
Integer from = (pageNum - 1) * pageSize;
if (from <= 0) {
from = 0;
}
searchSourceBuilder.from(from);
searchSourceBuilder.size(pageSize);
//设置一个可选的超时时间,用于可控制搜索允许的时间
searchSourceBuilder.timeout(new TimeValue(1200, TimeUnit.SECONDS));
//将数据按date排序
FieldSortBuilder sortBuilder = SortBuilders.fieldSort("createdate").order(SortOrder.DESC);
searchSourceBuilder.sort(sortBuilder);
//创建queryBuilder, 从es字段:name,content多字段查询
QueryBuilder queryBuilder = QueryBuilders.multiMatchQuery(keyWords, "name", "content").operator(Operator.OR);
searchSourceBuilder.query(queryBuilder);
//设置需要高亮的es字段
String preTags = "<span style='color:#29bf9d'>";
String postTags = "</span>";
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.preTags(preTags);//设置前缀
highlightBuilder.postTags(postTags);//设置后缀
highlightBuilder.field("name");//设置高亮字段
highlightBuilder.field("content");//设置高亮字段
//设置多个高亮显示为false,根据需求也可以设置为true
highlightBuilder.requireFieldMatch(false);
//下面这两项,如果你要高亮如文字内容等有很多字的字段,必须配置,不然会导致高亮不全,文章内容缺失等
highlightBuilder.fragmentSize(800000); //最大高亮分片数
highlightBuilder.numOfFragments(0); //从第一个分片获取高亮片段
searchSourceBuilder.highlighter(highlightBuilder);//设置高亮信息
searchRequest.source(searchSourceBuilder);
try {
SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//return toProductList(response.getHits().getHits()).stream().findFirst().orElse(null);
return toProductList(response.getHits().getHits());
//
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private List<Product> toProductList(SearchHit[] searchHits) throws Exception {
List<Product> productList = new ArrayList<>();
for (SearchHit searchHit : searchHits) {
Product Productinfo = JSON.parseObject(searchHit.getSourceAsString(), Product.class);
Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
if (!highlightFields.isEmpty()) {
HighlightField name = highlightFields.get("name");
if (name != null) {
Productinfo.setName(Arrays.stream(name.getFragments()).map(Text::string).collect(Collectors.joining("\n")));
}
HighlightField content = highlightFields.get("content");
if (content != null) {
Productinfo.setContent(Arrays.stream(content.getFragments()).map(Text::string).collect(Collectors.joining("\n")));
}
}
productList.add(Productinfo);
//productList.add(searchHit.getSourceAsMap());
//productList.add(objectMapper.readValue(searchHit.getSourceAsString(), Product.class));
//productList.add(objectMapper.readValue(searchHit.getSourceAsString(), Product.class));
}
return productList;
}
}