ES(Elasticsearch)的應用與代碼示例

Elasticsearch應用與代碼示例技術文章大綱

一、引言
  1. Elasticsearch在現代化應用中的核心作用
  2. 典型應用場景分析(日志分析/全文檢索/數據聚合)
二、環境準備(前提條件)
  1. Elasticsearch 8.x集群部署要點
  2. IK中文分詞插件配置指南
  3. Ingest Attachment插件安裝說明
三、核心代碼結構解析
src/main/
├── java/
│   ├── config/
│   │   └── ElasticSearchConfig.java
│   ├── controller/
│   │   └── ElasticSearchController.java
│   ├── service/
│   │   ├── ElasticSearchService.java
│   │   └── ElasticSearchServiceImpl.java
│   ├── model/
│   │   ├── FileData.java
│   │   ├── Attachment.java
│   │   └── SearchResult.java
│   ├── dto/
│   │   └── WarningInfoDto.java
│   └── util/
│       └── ElasticSearchUtils.java
四、核心組件實現(含代碼示例)

1. 配置中心(ElasticSearchConfig.java)
application.properties or yml

es.uri=192.168.1.1
es.port=9200
es.username=""
es.password=""
package com.zbxsoft.wds.config;import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.JsonpMapper;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import com.alibaba.fastjson.parser.deserializer.JSONPDeserializer;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** es配置*/
@Configuration
@ConfigurationProperties(prefix = "es")
public class ElasticSearchConfig{public String getUri() {return uri;}public void setUri(String uri) {this.uri = uri;}public Integer getPort() {return port;}public void setPort(Integer port) {this.port = port;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}private String uri;private Integer port;private String password;private String username;@Beanpublic ElasticsearchClient elasticsearchClient(@Autowired(required = false) JsonpMapper jsonpMapper, @Autowired(required = false) ObjectMapper objectMapper) {// 解析hostlist配置信息// 創建HttpHost數組,其中存放es主機和端口的配置信息HttpHost[] httpHostArray = new HttpHost[1];httpHostArray[0] = new HttpHost(uri,Integer.valueOf(port));RestClientBuilder builder = RestClient.builder(httpHostArray);final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();if(StringUtils.isNotBlank(username) && StringUtils.isNotBlank(password)){credentialsProvider.setCredentials(AuthScope.ANY,new UsernamePasswordCredentials(username, password));RestClient client = RestClient.builder(new HttpHost(uri,Integer.valueOf(port))).build();ElasticsearchTransport transport = new RestClientTransport(client, new JacksonJsonpMapper());return new ElasticsearchClient(transport);}RestClient restClient = builder.build();ElasticsearchTransport transport = null;if (jsonpMapper != null) {transport = new RestClientTransport(restClient, jsonpMapper);} else if (objectMapper != null) {transport = new RestClientTransport(restClient, new JacksonJsonpMapper(objectMapper));} else {transport = new RestClientTransport(restClient, new JacksonJsonpMapper());}// Create the transport with a Jackson mapper// And create the API clientreturn new ElasticsearchClient(transport);}
}

2. 數據處理模型(FileData.java)

package com.zbxsoft.wds.config;import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.zbxsoft.wds.fileupload.Attachment;
import lombok.Data;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;import java.io.Serializable;
import java.util.Objects;@Data
@Document(indexName = "file_data", createIndex = false)
@JsonIgnoreProperties(ignoreUnknown = true)
public class FileData implements Serializable {@Field(name = "file_id",type = FieldType.Text)private String file_id;@Field(name = "file_type",type = FieldType.Text)private String file_type;@Field(name = "file_name",type = FieldType.Text)private String file_name;@Field(name = "file_url",type = FieldType.Text)private String file_url;@Field(name = "file_size",type = FieldType.Text)private String file_size;@Field(name = "group_file_id",type = FieldType.Text)private String group_file_id;@Field(name = "file_suffix",type = FieldType.Text)private String file_suffix;@Field(name = "file_dir_name",type = FieldType.Text)private String file_dir_name;//保存時使用@Field(name = "attachment.content",type = FieldType.Text)private String content;//檢索時使用private Attachment attachment;}}

3. 附件解析組件(Attachment.java)

package com.zbxsoft.wds.fileupload;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;import java.io.Serializable;@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Attachment implements Serializable {private String date;private String content_type;private String author;private String language;private String title;private String content;private String content_length;
}}

4. 服務層實現(ElasticSearchService.java)

package com.zbxsoft.wds.fileupload;import com.baomidou.mybatisplus.core.metadata.IPage;
import com.zbxsoft.wds.config.FileData;
import org.springframework.http.HttpEntity;
import org.springframework.web.multipart.MultipartFile;import java.io.IOException;
import java.util.List;
import java.util.Map;public interface ElasticsearchService {HttpEntity<?> createFileIndex(MultipartFile file) throws IOException;String createFileIndex(FileData fileData) throws IOException;Map<String,Double> queryWord(String keyword) throws IOException;IPage<SearchResult> queryWord(WarningInfoDto warningInfoDto) throws IOException;List<String> getAssociationalWordOther(WarningInfoDto warningInfoDto);String updateFileIndex(String id, FileData fileData) throws IOException;
}

工具類(ElasticSearchUtils.java)

package com.zbxsoft.wds.config;import cn.hutool.extra.spring.SpringUtil;import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.Result;
import co.elastic.clients.elasticsearch._types.SortOptions;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregate;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregation;
import co.elastic.clients.elasticsearch._types.mapping.DateProperty;
import co.elastic.clients.elasticsearch._types.mapping.Property;
import co.elastic.clients.elasticsearch._types.mapping.TextProperty;
import co.elastic.clients.elasticsearch._types.mapping.TypeMapping;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.*;
import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem;
import co.elastic.clients.elasticsearch.core.search.HitsMetadata;
import co.elastic.clients.elasticsearch.core.search.TotalHits;
import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation;
import co.elastic.clients.elasticsearch.core.search.TrackHits;
import co.elastic.clients.elasticsearch.indices.*;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import lombok.extern.slf4j.Slf4j;import java.io.IOException;
import java.io.StringReader;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;@Slf4j
public class ElasticSearchUtils<T> {public static ElasticsearchClient elasticsearchClient;public String index;public Class obj;public String idField;public Set<String> fields;static {ElasticSearchConfig elasticSearchConfig = SpringUtil.getBean(ElasticSearchConfig.class);
//        elasticsearchClient = elasticSearchConfig.elasticsearchClient();}/*** 獲取id字段** @return*/private String getIdValue(T t) throws Exception {Field field = t.getClass().getDeclaredField(idField);field.setAccessible(true);Object object = field.get(t);return object.toString();}/*** 判斷索引是否存在** @return*/public Boolean getIndex() {try {GetIndexRequest getIndexRequest = GetIndexRequest.of(builder -> builder.index(index));GetIndexResponse getIndexResponse = elasticsearchClient.indices().get(getIndexRequest);log.info("getIndexResponse:{}", getIndexResponse);return true;} catch (IndexOutOfBoundsException | IOException e) {log.info("getIndexResponse:{}", e.getMessage());return false;}}public void deleteIndex() throws IOException {//1.創建索引請求DeleteIndexRequest request = DeleteIndexRequest.of(builder -> builder.index(index));//2.執行創建請求DeleteIndexResponse delete = elasticsearchClient.indices().delete(request);//如果為true就刪除了log.info("DeleteIndexRequest:{}", delete);}/*** 插入數據** @throws IOException*/public void push(T t) throws Exception {String id = getIdValue(t);IndexRequest<T> indexRequest = IndexRequest.of(b -> b.index(index).id(id).document(t)//刷新可以立刻搜索到,消耗性能/*.refresh(Refresh.True)*/);elasticsearchClient.index(indexRequest);}/*** 索引信息查詢** @throws IOException*/public T query(String id) throws IOException {GetResponse<T> response = elasticsearchClient.get(g -> g.index(index).id(id), obj);if (response.found()) {return response.source();}return null;}/*** 索引信息查詢** @throws IOException*/public HitsMetadata<T> queryList(int page, int pageSize, Query query, SortOptions... sortOptions) throws IOException {SearchResponse<T> search = elasticsearchClient.search(s -> s.index(index).query(query).trackTotalHits(TrackHits.of(i -> i.enabled(true))).sort(Arrays.asList(sortOptions)).from((page - 1) * pageSize).size(pageSize), obj);return search.hits();}/*** 刪除文檔** @throws IOException*/public boolean del(String id) throws IOException {DeleteResponse delete = elasticsearchClient.delete(d -> d.index(index).id(id));Result result = delete.result();return "deleted".equals(result.jsonValue()) | "not_found".equals(result.jsonValue());}/*** 批量** @throws IOException*/public Map<String, String> batchDel(Set<String> ids) throws Exception {BulkRequest.Builder br = new BulkRequest.Builder();for (String id : ids) {br.operations(op -> op.delete(d -> d.index(index).id(id)));}return requestBulk(br);}/*** 批量** @throws IOException*/public Map<String, String> batchAdd(List<T> list) throws Exception {BulkRequest.Builder br = new BulkRequest.Builder();for (T t : list) {String idValue = getIdValue(t);br.operations(op -> op.index(idx -> idx.index(index).id(idValue).document(t)));}return requestBulk(br);}/*** 處理批量請求** @param br* @return* @throws IOException*/private Map<String, String> requestBulk(BulkRequest.Builder br) throws IOException {//刷新可以立刻搜索到,消耗性能//br.refresh(Refresh.True);BulkResponse result = elasticsearchClient.bulk(br.build());System.out.println(result);Map<String, String> returnResult = new HashMap<>();if (result.errors()) {returnResult = result.items().stream().filter(e -> e.error() != null).collect(Collectors.toMap(BulkResponseItem::id, b -> b.error().reason()));}return returnResult;}/*** 分組* @param map* @return* @throws IOException*/public Map<String, Aggregate> buildAggregate(Map<String, Aggregation> map) throws IOException {SearchResponse<T> search = elasticsearchClient.search(s -> s.index(index).size(0).aggregations(map), obj);return search.aggregations();}public Long queryCount(Query query) throws IOException {CountResponse search = elasticsearchClient.count(s -> s.index(index).query(query));return search.count();}}

服務層實現(ElasticSearchServiceImpl.java)

package com.zbxsoft.wds.fileupload;import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.UUID;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.core.*;
import co.elastic.clients.elasticsearch.core.search.*;import com.aliyun.oss.ServiceException;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zbxsoft.wds.aneo4j.TextAnalysis;
import com.zbxsoft.wds.aneo4j.rep.CustomNeo4jRepository;
import com.zbxsoft.wds.filequery.FileQuery;
import com.zbxsoft.wds.mapper.FileQueryMapper;
import com.zbxsoft.wds.config.FileData;
import com.zbxsoft.xwk.vo.R;
import lombok.extern.slf4j.Slf4j;import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ResourceLoader;
import org.springframework.data.util.Pair;
import org.springframework.http.HttpEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.util.*;@Service
@Slf4j
public class ElasticsearchServiceImpl implements ElasticsearchService {@Autowiredprivate ElasticsearchClient client;@Autowiredprivate ResourceLoader resourceLoader;@Autowiredprotected FileQueryMapper fileQueryMapper;@Value("${file.server.address}")private String fileServerAddress;@Autowiredprivate CustomNeo4jRepository customNeo4jRepository;/*** 創建索引* @param fileData 文件數據* @return 索引id* @throws IOException exp*/public String createFileIndex(FileData fileData) throws IOException {String path = fileData.getFile_url();String url = fileServerAddress + path;log.info("已上傳文件地址:" + url);String fileName = FileUtil.getName(url);// 上傳并返回新文件名稱String prefix = fileName.substring(fileName.lastIndexOf(".") + 1);File file = File.createTempFile(fileName, prefix);IOUtils.copy(new URL(url),file);try (PDDocument document = PDDocument.load(file)) {//提取pdf中的文本內容PDFTextStripper pdfTextStripper = new PDFTextStripper();String text = pdfTextStripper.getText(document);//該主鍵 在es dm 中用作數據唯一id, 在neo4j中作為實體的typeString id = fileData.getFile_id();//提取文章中的關鍵詞List<String> keywords = TextAnalysis.getKeywords(text);if (CollectionUtil.isNotEmpty(keywords)) {//構建知識圖譜customNeo4jRepository.buildArticleKeywordGraph(id, keywords);//更新keywords字段 file_id 就是數據庫中存在的主鍵updateKeywords(id, String.join(",", keywords));}} catch (IOException e) {log.error("提取文本或創建關鍵詞圖譜失敗,異常信息: {}", e.toString());}//最后建立該文章的索引String _docId = createIndex(file,fileData);return _docId;}/*** 更新文件對象的keyword* @param id 主鍵* @param keyword 關鍵詞*/private void updateKeywords(String id,String keyword){LambdaUpdateWrapper<FileQuery> updateWrapper = new LambdaUpdateWrapper<>();updateWrapper.eq(FileQuery::getFileQueryId,id).set(FileQuery::getKeyword,keyword);fileQueryMapper.update(updateWrapper);}/*** 創建索引* @param file 文件* @param fileData 文件對象* @return 索引id*/private String createIndex(File file, FileData fileData) {try {byte[] bytes = getContent(file);String base64 = Base64.getEncoder().encodeToString(bytes);fileData.setContent(base64);IndexRequest<Object> requestData = IndexRequest.of(i -> i.index("file_data").pipeline("attachment").id(fileData.getFile_id()).document(fileData));IndexResponse indexResponse = client.index(requestData);log.info("indexResponse:" + indexResponse);return indexResponse.id();} catch (IOException e) {log.error("文件上傳異常,異常信息: {}", e.toString());return "";}}/*** 更新索引,在更新文件的時候發生* @param id 索引id 也是關系庫主鍵* @param fileData 文件對象* @return* @throws IOException*/@Overridepublic String updateFileIndex(String id, FileData fileData) throws IOException {//直接刪除索引, 重建DeleteRequest deleteRequest = DeleteRequest.of(s -> s.index("file_data").id(id));client.delete(deleteRequest);String _docId = createFileIndex(fileData);return _docId;}/*** 文件轉base64** @param file 文件對象* @return buffer* @throws IOException*/private byte[] getContent(File file) throws IOException {long fileSize = file.length();if (fileSize > Integer.MAX_VALUE) {log.info("file too big...");return null;}FileInputStream fi = new FileInputStream(file);byte[] buffer = new byte[(int) fileSize];int offset = 0;int numRead = 0;while (offset < buffer.length&& (numRead = fi.read(buffer, offset, buffer.length - offset)) >= 0) {offset += numRead;}// 確保所有數據均被讀取if (offset != buffer.length) {throw new ServiceException("Could not completely read file "+ file.getName());}return buffer;}/*** 給定keyword 檢索數據* @param keyword* @return* @throws IOException*/public Map<String,Double> queryWord(String keyword) throws IOException {SearchResponse<FileData> response = doQuery(keyword);log.info("檢索結果: {}", response.hits().hits());List<Pair<String,Double>> idList = Lists.newArrayList();Map<String,Double> idsWithScore = Maps.newHashMap();List<Hit<FileData>> hits = response.hits().hits();for (Hit<FileData> hit : hits) {Double score = hit.score();String id = hit.id();score = score == null ? 0.0d : score;idsWithScore.put(id,score);}log.info("查詢數據: {}", idsWithScore);return idsWithScore;}/*** es attachment.content 檢索封裝* @param keyword 關鍵詞* @return 檢索結果* @throws IOException exp*/private SearchResponse<FileData> doQuery(String keyword) throws IOException {Map<String, HighlightField> map = new HashMap<>();HighlightField build = new HighlightField.Builder().preTags("").postTags("").build();map.put("file_name",build);map.put("attachment.content",HighlightField.of(hf -> hf.preTags("").postTags("").numberOfFragments(4)));Highlight highlight = Highlight.of(h -> h.type(HighlighterType.of(ht -> ht.builtin(BuiltinHighlighterType.Unified))).fields(map).fragmentSize(50).numberOfFragments(5));//索引 file_name 分詞器 為ik_max_word 顆粒度較細  而attachment.content 使用ik_smart分詞器 , 顆粒度相對粗一點SearchResponse<FileData> response = client.search(s -> s.index("file_data").highlight(highlight).query(q -> q.bool(b -> b.should(sh -> sh.match(t -> t.field("file_name").query(keyword))).should(sh -> sh.match(t -> t.field("attachment.content").query(keyword))))),FileData.class);return response;}/*** 高亮分詞搜索其它類型文檔** @param warningInfoDto* @return*/public IPage<SearchResult> queryWord(WarningInfoDto warningInfoDto) throws IOException {//分頁SearchResponse<FileData> response = doQuery(warningInfoDto.getKeyword());//手動創建分頁對象IPage<SearchResult> warningInfoIPage = getFileDataIPage(warningInfoDto, response);return warningInfoIPage;}/*** 獲取檢索數據, 分頁* @param warningInfoDto* @param response* @return*/@NotNullprivate static IPage<SearchResult> getFileDataIPage(WarningInfoDto warningInfoDto, SearchResponse<FileData> response) {List<Hit<FileData>> hits = response.hits().hits();TotalHits total = response.hits().total();List<SearchResult> resultList = new LinkedList<>();//處理返回內容for (Hit<FileData> hit : hits) {Map<String, List<String>> map = hit.highlight();List<String> highLightWords = Lists.newArrayList();map.forEach((k,v) -> highLightWords.addAll(v));FileData fileData = hit.source();SearchResult searchResult = new SearchResult(fileData,highLightWords);resultList.add(searchResult);}//        //設置一個最后需要返回的實體類集合//手動分頁返回信息IPage<SearchResult> warningInfoIPage = new Page<>();assert total != null;warningInfoIPage.setTotal(total.value());warningInfoIPage.setRecords(resultList);warningInfoIPage.setCurrent(warningInfoDto.getPageIndex());warningInfoIPage.setSize(warningInfoDto.getPageSize());warningInfoIPage.setPages(warningInfoIPage.getTotal() % warningInfoDto.getPageSize());return warningInfoIPage;}/*** 文檔信息關鍵詞聯想(根據輸入框的詞語聯想文件名稱)** @param warningInfoDto* @return*/public List<String> getAssociationalWordOther(WarningInfoDto warningInfoDto) {
//        //需要查詢的字段
//        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery()
//                .should(QueryBuilders.matchBoolPrefixQuery("fileName", warningInfoDto.getKeyword()));
//        //contentType標簽內容過濾
//        boolQueryBuilder.must(QueryBuilders.termsQuery("contentType", warningInfoDto.getContentType()));
//        //構建高亮查詢
//        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
//                .withQuery(boolQueryBuilder)
//                .withHighlightFields(
//                        new HighlightBuilder.Field("fileName")
//                )
//                .withHighlightBuilder(new HighlightBuilder().preTags("<span style='color:red'>").postTags("</span>"))
//                .build();
//        //查詢
//        SearchHits<FileData> search = null;
//        try {
//            search = client.search(searchQuery);
//        } catch (Exception ex) {
//            ex.printStackTrace();
//            throw new ServiceException(String.format("操作錯誤,請聯系管理員!%s", ex.getMessage()));
//        }
//        //設置一個最后需要返回的實體類集合
//        List<String> resultList = new LinkedList<>();
//        //遍歷返回的內容進行處理
//        for (org.springframework.data.elasticsearch.core.SearchHit<FileInfo> searchHit : search.getSearchHits()) {
//            //高亮的內容
//            Map<String, List<String>> highlightFields = searchHit.getHighlightFields();
//            //將高亮的內容填充到content中
//            searchHit.getContent().setFileName(highlightFields.get("fileName") == null ? searchHit.getContent().getFileName() : highlightFields.get("fileName").get(0));
//            if (highlightFields.get("fileName") != null) {
//                resultList.add(searchHit.getContent().getFileName());
//            }
//        }
//        //list去重
//        List<String> newResult = null;
//        if (!FastUtils.checkNullOrEmpty(resultList)) {
//            if (resultList.size() > 9) {
//                newResult = resultList.stream().distinct().collect(Collectors.toList()).subList(0, 9);
//            } else {
//                newResult = resultList.stream().distinct().collect(Collectors.toList());
//            }
//        }return new ArrayList<>();}/*** 上傳文件并進行文件內容識別上傳到es 測試使用* @param file* @return*/public HttpEntity<?> createFileIndex(MultipartFile file) throws IOException {//http://192.168.100.243//file/wds/fileQuery/2024-12/1734319529179/downloadFile.pdf
//        InputStream inputStream = resourceLoader.getResource(url).getInputStream();String fileName = file.getName();String prefix = fileName.substring(fileName.lastIndexOf(".") + 1);File tempFile = File.createTempFile(fileName, prefix);// 上傳文件路徑file.transferTo(tempFile);FileData fileData = new FileData();fileData.setFile_url("http://localhost:9000/bucket/p2");fileData.setFile_id(UUID.fastUUID().toString(true));fileData.setFile_name("張飛吃豆芽333.pdf");fileData.setFile_suffix(".pdf");fileData.setFile_type("pdf");fileData.setFile_size("44");fileData.setFile_dir_name("p2");fileData.setGroup_file_id("g1");String _docId = createIndex(tempFile,fileData);return StringUtils.isBlank(_docId) ? R.badRequest("文件上傳異常") : R.success("文件上傳成功");}}
五、數據傳輸

1. 前端請求數據傳輸(WarningInfoDto.java)

package com.zbxsoft.wds.fileupload;import lombok.Data;import java.util.List;/*** 前端請求數據傳輸* WarningInfo* @author luoY*/
@Datapublic class WarningInfoDto{/*** 頁數*/private Integer pageIndex;/*** 每頁數量*/private Integer pageSize;/*** 查詢關鍵詞*/private String keyword;/*** 內容類型*/private List<String> contentType;/*** 用戶手機號*/private String phone;
}
}

2. 文檔全文檢索接口(ElasticSearchController.java)

package com.zbxsoft.wds.fileupload;import com.baomidou.mybatisplus.core.metadata.IPage;import com.zbxsoft.wds.common.R;import org.springframework.http.HttpEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.List;/*** es搜索引擎** @author luoy*/
@RestController
@RequestMapping("es")
public class ElasticsearchController {@Resourceprivate ElasticsearchService elasticsearchService;@PostMapping("/uploadFile")public HttpEntity<?> uploadFile(@RequestParam(required = false) MultipartFile file) throws IOException {return elasticsearchService.createFileIndex(file);}/*** 告警信息關鍵詞聯想** @param warningInfoDto* @return*/@PostMapping("getAssociationalWordDoc")public HttpEntity<?> getAssociationalWordDoc(@RequestBody WarningInfoDto warningInfoDto, HttpServletRequest request) {List<String> words = elasticsearchService.getAssociationalWordOther(warningInfoDto);return R.list(words);}/*** 告警信息高亮分詞分頁查詢** @param warningInfoDto* @return*/@PostMapping("queryHighLightWordDoc")public HttpEntity<?> queryHighLightWordDoc(@RequestBody WarningInfoDto warningInfoDto,HttpServletRequest request) throws IOException {IPage<SearchResult> warningInfoListPage = elasticsearchService.queryWord(warningInfoDto);return R.entity(warningInfoListPage);}
}

3. 數據返回(SearchResult.java)

package com.zbxsoft.wds.fileupload;import com.zbxsoft.wds.config.FileData;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;import java.io.Serializable;
import java.util.List;@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class SearchResult implements Serializable {private FileData fileData;private List<String> highLightWords;
}
六、高級功能實現
  1. 多條件復合查詢構建技巧
  2. 聚合統計實現方案
  3. 搜索高亮顯示配置
七、性能優化建議
  1. 索引分片策略設計
  2. 查詢DSL優化技巧
  3. 批量操作最佳實踐
八、總結與展望
  1. 當前架構優勢分析
  2. 后續演進方向建議

(注:各代碼示例需配合完整的類定義和import語句,實際開發中需補充異常處理、日志記錄等生產級代碼要素)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/905742.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/905742.shtml
英文地址,請注明出處:http://en.pswp.cn/news/905742.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

臨床決策支持系統的提示工程優化路徑深度解析

引言 隨著人工智能技術在醫療領域的迅猛發展,臨床決策支持系統(CDSS)正經歷從傳統規則引擎向智能提示工程的范式轉變。在這一背景下,如何構建既符合循證醫學原則又能適應個體化醫療需求的CDSS成為醫學人工智能領域的核心挑戰。本報告深入剖析了臨床決策支持系統中提示工程的…

火山RTC 8 SDK集成進項目中

一、SDK 集成預備工作 1、SDK下載 https://www.volcengine.com/docs/6348/75707 2、解壓后 3、放在自己項目中的位置 1&#xff09;、include 2&#xff09;、lib 3)、dll 暫時&#xff0c;只需要VolcEngineRTC.dll RTCFFmpeg.dll openh264-4.dll&#xff0c; 放在intLive2…

OkHttp用法-Java調用http服務

特點&#xff1a;高性能&#xff0c;支持異步請求&#xff0c;連接池優化 官方文檔&#xff1a;提供快速入門指南和高級功能&#xff08;如攔截器、連接池&#xff09;的詳細說明&#xff0c;GitHub倉庫包含豐富示例。 社區資源&#xff1a;中文教程豐富&#xff0c;GitHub高…

python中常用的參數以及命名規范

以下是 Python 中常見的命名規范、參數用法及在大型項目中常用的操作模式&#xff0c;供記錄參考&#xff1a; 1. 命名規范&#xff08;Naming Conventions&#xff09; 前綴/形式含義示例_age單下劃線&#xff1a;弱“私有”標記&#xff08;可訪問但不建議外部使用&#xff…

第五十七篇 Java接口設計之道:從咖啡機到智能家居的編程哲學

目錄 引言&#xff1a;生活中的接口無處不在一、咖啡機與基礎接口&#xff1a;理解抽象契約1.1 咖啡制作的標準接口 二、智能家居與策略模式&#xff1a;靈活切換實現2.1 溫度調節策略場景 三、物流系統與工廠模式&#xff1a;標準接口下的多樣實現3.1 快遞運輸接口設計 四、健…

第二十六天打卡

全局變量 global_var 全局變量是定義在函數、類或者代碼塊外部的變量&#xff0c;它在整個程序文件內都能被訪問。在代碼里&#xff0c; global_var 就是一個全局變量&#xff0c;下面是相關代碼片段&#xff1a; print("\n--- 變量作用域示例 ---") global_var …

聯合查詢

目錄 1、笛卡爾積 2、聯合查詢 2.1、內連接 2.2、外連接 1、笛卡爾積 笛卡爾積&#xff1a; 笛卡爾積是讓兩個表通過排列組合的方式&#xff0c;得到的一個更大的表。笛卡爾積的列數&#xff0c;是這兩個表的列數相加&#xff0c;笛卡爾積的行數&#xff0c;是這兩個表的行…

【HTML5學習筆記2】html標簽(下)

1表格標簽 1.1表格作用 顯示數據 1.2基本語法 <table><tr> 一行<td>單元格1</td></tr> </table> 1.3表頭單元格標簽 表頭單元格會加粗并且居中 <table><tr> 一行<th>單元格1</th></tr> </table&g…

window 顯示驅動開發-分頁視頻內存資源

與 Microsoft Windows 2000 顯示驅動程序模型不同&#xff0c;Windows Vista 顯示驅動程序模型允許創建比可用物理視頻內存總量更多的視頻內存資源&#xff0c;然后根據需要分頁進出視頻內存。 換句話說&#xff0c;并非所有視頻內存資源都同時位于視頻內存中。 GPU 的管道中可…

《C 語言指針高級指南:字符、數組、函數指針的進階攻略》

目錄 一. 字符指針變量 二. 數組指針變量 三. 二維數組傳參 3.1 二維數組的本質 3.2 訪問方式與地址計算 3.3 二維數組的傳參方式 3.4 深入解析 *(*(arri)j) 與 arr[i][j] 的等價性 四. 函數指針變量 4.1 函數指針變量的創建 4.2 函數指針變量的使用 4.3 兩段"…

Unity:場景管理系統 —— SceneManagement 模塊

目錄 &#x1f3ac; 什么是 Scene&#xff08;場景&#xff09;&#xff1f; Unity 項目中的 Scene 通常負責什么&#xff1f; &#x1f30d; 一個 Scene 包含哪些元素&#xff1f; Scene 的切換與管理 &#x1f4c1; 如何創建與管理 Scenes&#xff1f; 什么是Scene Man…

內容中臺重構企業知識管理路徑

智能元數據驅動知識治理 現代企業知識管理的核心挑戰在于海量非結構化數據的有效治理。通過智能元數據分類引擎&#xff0c;系統可自動識別文檔屬性并生成多維標簽體系&#xff0c;例如將技術手冊按產品版本、功能模塊、適用場景進行動態標注。這種動態元數據框架不僅支持跨部…

Vue3:腳手架

工程環境配置 1.安裝nodejs 這里我已經安裝過了&#xff0c;只需要打開鏈接Node.js — Run JavaScript Everywhere直接下載nodejs&#xff0c;安裝直接一直下一步下一步 安裝完成之后我們來使用電腦的命令行窗口檢查一下版本 查看npm源 這里npm源的地址是淘寶的源&#xff0…

悅數圖數據庫一體機發布,讓復雜關聯計算開箱即用

在金融風控、政務治理、能源監測等關鍵領域&#xff0c;復雜數據關聯分析已成為業務決策的核心需求。然而&#xff0c;信創場景的特殊性——全棧自主可控、海量實時計算、系統高可用性——對傳統技術架構提出了近乎苛刻的要求。悅數圖數據庫一體機應運而生&#xff0c;以軟硬協…

收放卷“材料停機減速距離“計算FC(算法公式+ST源代碼+C++代碼)

PLC運動控制基礎系列之梯形速度曲線 PLC運動控制基礎系列之梯形速度曲線_三菱運動控制模塊梯形加減速-CSDN博客文章瀏覽閱讀3.2k次,點贊3次,收藏7次。本文是關于PLC運動控制的基礎教程,重點介紹了梯形速度曲線的概念、計算和應用。討論了梯形加減速在啟動和停止階段的作用,…

Centos7系統(最小化安裝)安裝zabbix7版本詳細文章、nginx源代碼配置、php源代碼、mysql-yum安裝

zabbix官網鏈接下載zabbix源代碼安裝包 選擇zabbix版本&#xff08;此文章使用zabbix7.0版本&#xff09; 安裝之前由于是最小化安裝centos7安裝一些開發環境和工具包 文章使用國內阿里源 cd /etc/yum.repos.d/;curl -O https://mirrors.aliyun.com/repo/epel-7.repo;curl -…

描述性統計圖表

一、核心圖表類型與用途 1、直方圖(Histogram) (1)定義:用連續矩形表示數據分布,橫軸為數據區間,縱軸為頻數或頻率。 (2)用途:展示數據分布形態(對稱、偏態)、識別離群值。 (3)適用場景:分析連續型變量的分布特征,如收入分布、考試成績分布。 2、箱線圖(Box P…

ThinkPad X250電池換電池芯(理論技術儲備)

參考&#xff1a;筆記本電池換電芯的經驗與心得分享 - 經典ThinkPad專區 - 專門網 換電池芯&#xff0c;需要克服以下問題&#xff1a; 1 拆電池。由于是超聲波焊接&#xff0c;拆解比較費力&#xff0c;如果暴力撬&#xff0c;有可能導致電池殼變形... 2 替換電池芯的時候如…

Java(基礎) day01 初識Java

目錄 一、運行Java程序 二、基本數據類型 1、整數類型 ?編輯2、浮點型 3、字符型 4、布爾類型 一、運行Java程序 Java是一門半編譯型、半解釋型語言。先通過javac編譯程序把xxx.java源文件進行編譯&#xff0c;編譯后生成的.class文件是由字節碼組成的平臺無關、面向JVM的文…

【美團】Java后端一面復盤|網絡+線程+MySQL+Redis+設計模式+手撕算法

&#x1f4cd; 面試公司&#xff1a;美團 &#x1f3af; 面試崗位&#xff1a;Java后端開發工程師 &#x1f4de; 面試形式&#xff1a;電話面試 &#x1f552; 面試時長&#xff1a;約 50 分鐘 &#x1f501; 面試輪次&#xff1a;第一輪技術面 ? 面試整體節奏&#xff1a; …