本文使用的是阿里云elasticsearch6.7版本
官方API地址:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/6.7/java-rest-high-search.html
/**
* 创建索引
* @param index
* @throws IOException
*/
public String createIndex(String index) {
String result = "成功";
try {
if (!checkIndexExists(index)) {
logger.info("开始新建索引【{}】", index);
CreateIndexRequest request = new CreateIndexRequest(index);
//如果有特殊字段-如日期等 需要自己定义字段类型
/*Map<String, Object> updateTime = new HashMap<>(1);
updateTime.put("type", "date");
updateTime.put("format", "yyyy-MM-dd'T'HH:mm:ss");
Map<String, Object> properties = new HashMap<>(1);
properties.put("updateTime", updateTime);
Map<String, Object> mapping = new HashMap<>(1);
mapping.put("properties", properties);
request.mapping(mapping);*/
CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
logger.info("createIndex: {}", JSON.toJSONString(createIndexResponse));
if (!createIndexResponse.isAcknowledged()) {
result = "接口执行失败";
}
} else {
logger.info("索引【{}】已存在,无需重建", index);
result = "索引【" + index + "】已存在,无需重复创建";
}
} catch (Exception ex) {
logger.error("createIndex 索引创建接口异常,{}", ex);
result = "索引创建接口异常";
}
return result;
}
/**
* 删除索引
* @param index
* @return
* @throws IOException
*/
public boolean deleteIndex(String index) throws IOException {
/**
* 返回true是成功 反之失败
* 如果索引不存在会出异常 Elasticsearch exception [type=index_not_found_exception, reason=no such index]
*/
//先检查索引是否存在
if (!checkIndexExists(index)) {
logger.info("索引【{}】不存在,不走删除逻辑", index);
return false;
}
DeleteIndexRequest deleteRequest = new DeleteIndexRequest(index);
logger.info("开始删除索引,name=【{}】的数据", index);
AcknowledgedResponse dResponse = restHighLevelClient.indices().delete(deleteRequest, RequestOptions.DEFAULT);
logger.info("删除后返回结果:{}", dResponse.isAcknowledged());
return dResponse.isAcknowledged();
}
/**
* 验证索引是否存在
* @param index
* @return
* @throws IOException
*/
public boolean checkIndexExists(String index) throws IOException {
GetIndexRequest getIndexRequest = new GetIndexRequest(index);
boolean exists = restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
logger.info("验证索引【{}】是否存在结果为: {}", index, exists);
return exists;
}
/**
* 文档内容写入es
* Ingest-Attachment
* Ingest Node
* test
*/
public int saveDocumentByIndex(String index, String type, DocumentVo vo, SyncDocumentLog syncDocumentLog) {
try {
if (vo.getUrl() == null) {
return ErrorUtil.ES_FILE_STATUS_3.getCode();
}
if (vo.getUrl().indexOf(ossUrl) == -1) {
//解决测试环境文档内容不匹配问题
return ErrorUtil.ES_FILE_STATUS_2.getCode();
}
if (!StringUtils.isEmpty(syncDocumentLog.getEsDocId())) {
//删除旧的数据
deleteDocumentById(index, type, syncDocumentLog.getEsDocId());
}
String path = vo.getUrl();
String butkey = path.substring(ossUrl.length() + 1, path.length());
path = path.replace("\\", "/");
//这里的base64要换成官方的方法 否则转化出错
String content = ossService.fileToBase64ByOssUrl(butkey);
Map<String, Object> paramMap = new HashMap<>(6);
paramMap.put(DocumentKey.doc_id.getKey(), vo.getId());
paramMap.put(DocumentKey.doc_fileName.getKey(), vo.getName());
paramMap.put(DocumentKey.doc_data.getKey(), content);
paramMap.put(DocumentKey.doc_updateTime.getKey(), vo.getUpdateTime());
paramMap.put(DocumentKey.doc_filePath.getKey(), path);
paramMap.put(DocumentKey.doc_postfix.getKey(), vo.getPostfix());
paramMap.put(DocumentKey.doc_chipCode.getKey(), vo.getChipCode());
paramMap.put(DocumentKey.doc_chipProjectCode.getKey(), vo.getChipProjectCode());
IndexRequest indexRequest = new IndexRequest(index, type);
indexRequest.source(paramMap, XContentType.JSON);
indexRequest.setPipeline(DocumentKey.doc_Pipeline.getKey());
indexRequest.timeout("60s");
IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
logger.info("存入es执行完毕:docId=【{}】,code={}", vo.getId(), indexResponse.status().getStatus());
//保存es的id到这边 方便查询
syncDocumentLog.setEsDocId(indexResponse.getId());
return indexResponse.status().getStatus();
} catch (Exception ex) {
syncDocumentLog.setEsDocId("");
syncDocumentLog.setRemark(ex.getMessage());
logger.error("保存文档内容到es时出错,docId=【{}】,type=【{}】,error: {}", vo.getId(), vo.getPostfix(), ex.getMessage());
return ElasticStatus.SYNCING_CODE.getCode();
}
}
/**
* 根据关键字查找文档内容
* 返回 page
* @param queryVo
* @return
*/
public PageList<DocumentResult> findDocument(PageSortHighLight page, IndexData index, DocQueryVo queryVo) throws IOException {
PageList<DocumentResult> result = new PageList<>();
List<DocumentResult> queryList = new ArrayList<>(page.getPageSize());
String field_id = DocumentKey.doc_id.getKey();
String field_fileName = DocumentKey.doc_fileName.getKey();
String field_content = "attachment.content";
//高亮截取部分
int splitSize = 400;
//1.分页
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//从第0个开始
sourceBuilder.from(page.getCurrentPage()*page.getPageSize());
//相当于 limit
sourceBuilder.size(page.getPageSize());
// 获取的字段(列)和不需要获取的列
sourceBuilder.fetchSource(new String[]{DocumentKey.doc_id.getKey(), DocumentKey.doc_fileName.getKey(),
DocumentKey.doc_Pipeline.getKey(), DocumentKey.doc_filePath.getKey(), DocumentKey.doc_postfix.getKey(),
DocumentKey.doc_updateTime.getKey(), DocumentKey.doc_chipProjectCode.getKey(), DocumentKey.doc_chipCode.getKey()},
new String[]{DocumentKey.doc_data.getKey()});
// 设置排序规则--默认是命中分数最高者排前面
sourceBuilder.sort(new ScoreSortBuilder());
// 设置超时时间为2s
sourceBuilder.timeout(new TimeValue(10000));
//文件名称 也能匹配--fileName
MatchQueryBuilder matchQueryBuilder2 = QueryBuilders.matchQuery(field_fileName, queryVo.getKeyWord());
//文档内容匹配
MatchQueryBuilder matchQueryBuilder1 = QueryBuilders.matchQuery(field_content, queryVo.getKeyWord());
BoolQueryBuilder shouldQuery1 = QueryBuilders.boolQuery();
BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
if (!StringUtils.isEmpty(queryVo.getChipProjectCode())) {
//按项目CODE查询
BoolQueryBuilder shouldProject = QueryBuilders.boolQuery();
BoolQueryBuilder shouldChipAndPro = QueryBuilders.boolQuery();
// matchPhraseQuery
MatchPhraseQueryBuilder matchPhraseQueryBuilderPro = QueryBuilders.matchPhraseQuery(DocumentKey.doc_chipProjectCode.getKey(), queryVo.getChipProjectCode());
//or 还有一种情况
MatchPhraseQueryBuilder matchPhraseQueryBuilderChip1 = QueryBuilders.matchPhraseQuery(DocumentKey.doc_chipCode.getKey(), queryVo.getChipCode());
MatchPhraseQueryBuilder matchPhraseQueryBuilderChip2 = QueryBuilders.matchPhraseQuery(DocumentKey.doc_chipProjectCode.getKey(), "");
boolBuilder.must(shouldProject.should(matchPhraseQueryBuilderPro).should(shouldChipAndPro.must(matchPhraseQueryBuilderChip1).must(matchPhraseQueryBuilderChip2)));
} else {
//全盘查询
TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery(field_id, queryVo.getDocIdList());
boolBuilder.must(termsQueryBuilder);
}
//按时间段查询
if (!StringUtils.isEmpty(queryVo.getTimeStr())) {
//rangeQuery--当前时间
RangeQueryBuilder rangeQueryTime = QueryBuilders.rangeQuery(DocumentKey.doc_updateTime.getKey()).from(DateFormatUtil.formatDateByStr(queryVo.getTimeStr()))
.to(DateFormatUtil.formatDate(new Date()));
boolBuilder.must(rangeQueryTime);
}
//or 查询 其下满足其一即可BoolQueryBuilder 嵌套
boolBuilder.must(shouldQuery1.should(matchQueryBuilder2).should(matchQueryBuilder1));
sourceBuilder.query(boolBuilder);
//3.设置查询高亮显示--使用默认后缀
HighlightBuilder highlightBuilder = new HighlightBuilder();
String preTags = "<em class='titleColor' style='color: #f60'>";
String postTags = "</em>";
//设置前缀-后缀
highlightBuilder.preTags(preTags);
highlightBuilder.postTags(postTags);
//使用默认标签包裹
//highlightBuilder.highlighterType("Unified");
//设置高亮的字段名
highlightBuilder.field(field_content, splitSize);
highlightBuilder.field(field_fileName, 0);
sourceBuilder.highlighter(highlightBuilder);
// 4.创建并设置SearchRequest对象
SearchRequest searchRequest = new SearchRequest();
// 设置request要搜索的索引和类型
searchRequest.indices(index.getIndexName()).types(index.getIndexType());
// 设置SearchSourceBuilder查询属性
searchRequest.source(sourceBuilder);
long start = System.currentTimeMillis();
// 5.查询
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//取出结果对象
SearchHits hits = searchResponse.getHits();
logger.info("命中总数=【{}】,命中的最高分数=【{}】", hits.getTotalHits(), hits.getMaxScore());
result.setList(dealResult(queryList, hits, field_fileName, field_content, splitSize));
result.setTotalElements(hits.getTotalHits());
result.setTotalPages(getTotalPages(hits.getTotalHits(), page.getPageSize()));
long end = System.currentTimeMillis();
logger.info("根据search方法查询,耗时:{} 秒", (end-start)/1000);
return result;
}
/**
* 批量操作
* 支持 新增 修改 删除
* 只支持文档类型
* @param request
* @return
*/
public int bulkDocuments(BulkRequest request) {
//管道声明
request.pipeline(DocumentKey.doc_Pipeline.getKey());
//10分钟后超时
request.timeout("10m");
try {
logger.info("开始执行ES批量操作接口...");
BulkResponse bulkResponse = restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
logger.info("执行返回结果(200是成功):code={},异常日志:{}", bulkResponse.status().getStatus(), bulkResponse.buildFailureMessage());
return bulkResponse.status().getStatus();
} catch (IOException e) {
e.printStackTrace();
}
return 0;
}
/**
* 查询索引分类下的总记录数
* @param indexData
* @return
*/
public int countByIndexType(IndexData indexData) {
logger.info("开始查询索引【{}】分类【{}】下的总记录数.", indexData.getIndexName(), indexData.getIndexType());
try {
SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//关闭检索内容--只关心数量,不关心字段值
sourceBuilder.fetchSource(false);
//设置一个可选的超时,控制允许搜索的时间
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
searchRequest.source(sourceBuilder);
// 设置request要搜索的索引和类型
searchRequest.indices(indexData.getIndexName()).types(indexData.getIndexType());
SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//获取匹配的总数量
long total = search.getHits().getTotalHits();
logger.info("查询结束,总数:{}", total);
return (int) total;
} catch (Exception ex) {
logger.error("countByIndexType 查询总记录出错...{}", ex);
}
return 0;
}
待续…