package com.search.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.search.ao.DocumentIndexAO;
import com.search.ao.SearchObject;
import com.search.constant.SearchConstant;
import com.search.enums.SearchFieldEnum;
import com.search.query.SearchContentQuery;
import com.search.result.Result;
import com.search.service.DocumentService;
import com.search.util.FileResolve;
import com.search.util.FileUtil;
import com.search.util.RestClientUtil;
import com.search.vo.SearchResultVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.index.query.BoolQueryBuilder;
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.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
/**
* @author: liJin
* @description: <全文搜索服务实现类>
* @date: 2021-02-10
*/
@Slf4j
@Service
@Primary
public class DocumentServiceImpl implements DocumentService {
@Value("${searchIndexName}")
private String searchIndexName;
@Value("${operateIndexName}")
private String operateIndexName;
@Value("${smartBoost}")
private float smartBoost;
@Value("${ngramBoost}")
private float ngramBoost;
// 搜索的高亮的基础字段
private static final String[] BASE_HIGHLIGHT_FIELDS = new String[]{
SearchFieldEnum.NAME.getSmart(),
SearchFieldEnum.CONTENT.getSmart(),
SearchFieldEnum.NAME.getNgram(),
SearchFieldEnum.CONTENT.getNgram(),
};
private final RestClientUtil restClientUtil;
public DocumentServiceImpl(RestClientUtil restClientUtil) {
this.restClientUtil = restClientUtil;
}
private static <T> Map<String, Object> beanToMap(T bean) {
Map<String, Object> map = new HashMap<>();
if (bean != null) {
BeanMap beanMap = BeanMap.create(bean);
for (Object key : beanMap.keySet()) {
if (beanMap.get(key) != null) {
map.put(key + "", beanMap.get(key));
}
}
}
return map;
}
@Override
public void addDocument(List<DocumentIndexAO> documentIndexAOList) {
documentIndexAOList.forEach(item -> {
addDocument(item);
});
}
public void addDocument(DocumentIndexAO documentIndexAO) {
log.info("开始创建索引");
long begin = System.currentTimeMillis();
String fileContent;
try {
if (SearchConstant.DEFAULT_TYPE == documentIndexAO.getContentType()) {
fileContent = FileUtil.getFileRead(documentIndexAO.getFilePath(), "utf-8");
} else {
fileContent = documentIndexAO.getFileContent();
}
String content = FileResolve.delHTMLTag(fileContent);
documentIndexAO.setName(documentIndexAO.getManualDesc());
documentIndexAO.setContent(content);
documentIndexAO.setFullContent(content);
documentIndexAO.setFullName(documentIndexAO.getManualDesc());
documentIndexAO.setSectionTitle(documentIndexAO.getManualDesc());
documentIndexAO.setRealManualType(documentIndexAO.getRealManualType());
documentIndexAO.setSectionName(documentIndexAO.getSectionName());
documentIndexAO.setOriginalContent(content);
IndexRequest request = new IndexRequest(operateIndexName).id(documentIndexAO.getManualId()).source(beanToMap(documentIndexAO));
IndexResponse response = restClientUtil.index(request, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
log.error("文件索引创建失败……");
}
log.info("文件索引创建成功……");
long end = System.currentTimeMillis();
log.info("共耗时 {} ms……", (end - begin));
}
@Override
public Map<String, Object> getDocument(String id) {
GetRequest request = new GetRequest(operateIndexName, id);
try {
GetResponse response = restClientUtil.get(request, RequestOptions.DEFAULT);
return response.getSource();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
public void updateIndexById(DocumentIndexAO documentIndexAO) throws IOException {
UpdateRequest request = new UpdateRequest(operateIndexName, documentIndexAO.getManualId()).doc(beanToMap(documentIndexAO));
UpdateResponse response = restClientUtil.update(request, RequestOptions.DEFAULT);
}
@Override
public void deleteIndexById(String id) {
try {
DeleteRequest deleteRequest = new DeleteRequest(operateIndexName, id);
restClientUtil.delete(deleteRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void deleteIndexByField(String fieldName, String fieldValue) throws Exception {
log.info("开始删除索引[{}: {}]", fieldName, fieldValue);
for (int i = 0; i < 10; i++) {
SearchResponse response = termQueryByField(fieldName, fieldValue);
SearchHits hits = response.getHits();
if (hits.getHits().length == 0) {
break;
}
for (SearchHit hit : hits) {
String docId = hit.getId();
deleteIndexById(docId);
}
}
log.info("结束删除索引[{}: {}]", fieldName, fieldValue);
}
private SearchResponse termQueryByField(String fieldName, String fieldValue) throws IOException {
SearchRequest searchRequest = new SearchRequest(operateIndexName);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.termQuery(fieldName, fieldValue));
searchRequest.source(searchSourceBuilder);
searchSourceBuilder.from(SearchConstant.DEFAULT_FROM);
searchSourceBuilder.size(SearchConstant.DEFAULT_SIZE);
return restClientUtil.search(searchRequest, RequestOptions.DEFAULT);
}
/**
* 简单搜索,结果高亮
*/
@Override
public Result simpleSearch(SearchContentQuery query) {
// 根据条件 构建ES查询
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
buildBaseQuery(queryBuilder, query.getSearchField(), query.getSearchContent());
buildBaseQueryWithExtend(queryBuilder, query);
buildCommonCondition(queryBuilder, query);
// 高亮相关字段
HighlightBuilder highlightBuilder = new HighlightBuilder();
restClientUti
评论10