• springboot+Elasticsearch进阶


    1. package com.admin.model;
    2. import com.fasterxml.jackson.annotation.JsonFormat;
    3. import com.admin.common.entity.BaseSJFZEntity;
    4. import lombok.Data;
    5. import org.springframework.data.elasticsearch.annotations.Document;
    6. import org.springframework.data.elasticsearch.annotations.Field;
    7. import org.springframework.data.elasticsearch.annotations.FieldType;
    8. import java.util.Date;
    9. /**
    10. * Es 索引库实体
    11. *
    12. * @author wangwei
    13. * @date 2024-04-25
    14. */
    15. /***
    16. * esmodel8、 esmodel9 是存储在es中的索引类型
    17. */
    18. @Document(indexName = "esmodel9")
    19. @Data
    20. public class EsModel extends BaseSJFZEntity {
    21. /*** 索引id*/
    22. @Field(type = FieldType.Long)
    23. private String id;
    24. /**** es中对应的数据库业务单据id*/
    25. @Field(analyzer = "ik_max_word")
    26. private String ctId;
    27. /**** es中业务数据 对应的业务数据库表名称*/
    28. @Field(analyzer = "ik_max_word")
    29. private String ctTableName;
    30. /**** es中业务数据 对应的 业务简称*/
    31. @Field(analyzer = "ik_max_word")
    32. private String ctName;
    33. /**** es中业务数据 对应的 业务内容详细信息*/
    34. @Field(analyzer = "ik_max_word")
    35. private String ctContent;
    36. /* *//** 创建者 *//*
    37. //@Field(analyzer = "ik_max_word")
    38. private String createUser;
    39. *//** 创建时间 *//*
    40. @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    41. //@Field(analyzer = "ik_max_word")
    42. private Date createTime;
    43. *//** 更新者 *//*
    44. // @Field(analyzer = "ik_max_word")
    45. private String updateUser;
    46. *//** 更新时间 *//*
    47. @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    48. // @Field(analyzer = "ik_max_word")
    49. private Date updateTime;*/
    50. /** 备注 */
    51. @Field(analyzer = "ik_max_word")
    52. private String remark;
    53. /** 备用1 */
    54. @Field(analyzer = "ik_max_word")
    55. private String by1;
    56. /** 备用2 */
    57. @Field(analyzer = "ik_max_word")
    58. private String by2;
    59. /** 备用3 */
    60. @Field(analyzer = "ik_max_word")
    61. private String by3;
    62. /** 备用4 */
    63. @Field(analyzer = "ik_max_word")
    64. private String by4;
    65. /** 备用5 */
    66. @Field(analyzer = "ik_max_word")
    67. private String by5;
    68. }

    2.

    1. package com.admin.controller;
    2. import com.admin.common.annotation.Log;
    3. import com.admin.common.core.controller.BaseController;
    4. import com.admin.common.core.domain.AjaxResult;
    5. import com.admin.common.core.page.TableDataInfo;
    6. import com.admin.common.enums.BusinessType;
    7. import com.admin.model.EsModel;
    8. import com.admin.service.EsService;
    9. import io.swagger.annotations.Api;
    10. import io.swagger.annotations.ApiOperation;
    11. import org.springframework.beans.factory.annotation.Autowired;
    12. import org.springframework.data.domain.Pageable;
    13. import org.springframework.web.bind.annotation.*;
    14. import java.util.List;
    15. /**
    16. * es -spi
    17. *
    18. * @author wangwei
    19. * @date 2024-04-25
    20. */
    21. @Api(tags = "ES-api")
    22. @RestController
    23. @RequestMapping("/es/api")
    24. public class EsController extends BaseController {
    25. @Autowired
    26. private EsService esService;
    27. /***
    28. *从es中按指定字段值获取数据
    29. * @param key
    30. * @return
    31. */
    32. @ApiOperation(value = "查询 从es中按指定字段值获取数据")
    33. @GetMapping("/list")
    34. public AjaxResult list(String key, Pageable pageable) {
    35. AjaxResult ajaxResult = esService.searchES(key, pageable);
    36. return ajaxResult;
    37. }
    38. /***
    39. * 全文检索
    40. *查询 从es中全文检索所包含的 业务数据信息
    41. * eg:es中的数据字段有 name, contene,等,接口查询条件key 包含在所有字段中的业务数据信息
    42. * @param key
    43. * @return
    44. */
    45. @ApiOperation(value = "查询 从es中全文检索所包含的 业务数据信息")
    46. @GetMapping("/whole")
    47. public TableDataInfo searchWhole(String key, Pageable pageable) {
    48. List<EsModel> list = esService.searchWhole(key, pageable);
    49. return getDataTable(list);
    50. }
    51. /****
    52. * es中数据新增
    53. */
    54. @ApiOperation(value = "es中数据新增" )
    55. @Log(title = "es中数据新增" , businessType = BusinessType.INSERT)
    56. @PostMapping
    57. public AjaxResult add(@RequestBody EsModel esModel) {
    58. return toAjax(esService.insertEsModel(esModel));
    59. }
    60. /****
    61. * es中数据修改
    62. */
    63. @ApiOperation(value = "es中数据修改" )
    64. @Log(title = "es中数据修改" , businessType = BusinessType.UPDATE)
    65. @PutMapping
    66. public AjaxResult put(@RequestBody EsModel esModel) {
    67. return toAjax(esService.updateEsModel(esModel));
    68. }
    69. /**
    70. * 删除es中的数据
    71. */
    72. @ApiOperation(value = "删除es中的数据")
    73. @Log(title = "删除es中的数据", businessType = BusinessType.DELETE)
    74. @DeleteMapping("/{ctId}")
    75. public AjaxResult remove(@PathVariable String ctId) {
    76. return toAjax(esService.deleteById(ctId));
    77. }
    78. }

    3.

    1. package com.admin.service.impl;
    2. import com.admin.common.core.domain.AjaxResult;
    3. import com.admin.common.exception.CustomException;
    4. import com.admin.common.utils.StringUtils;
    5. import com.admin.constant.EsConstants;
    6. import com.admin.model.EsModel;
    7. import com.admin.repository.EsModelRepository;
    8. import com.admin.service.EsService;
    9. import com.admin.util.HighlightResultMapper;
    10. import com.alibaba.fastjson.JSON;
    11. import org.elasticsearch.action.update.UpdateRequest;
    12. import org.elasticsearch.action.update.UpdateResponse;
    13. import org.elasticsearch.client.RequestOptions;
    14. import org.elasticsearch.client.RestHighLevelClient;
    15. import org.elasticsearch.common.xcontent.XContentType;
    16. import org.elasticsearch.index.query.QueryBuilders;
    17. import org.elasticsearch.search.builder.SearchSourceBuilder;
    18. import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
    19. import org.elasticsearch.search.sort.SortBuilders;
    20. import org.elasticsearch.search.sort.SortOrder;
    21. import org.springframework.beans.factory.annotation.Autowired;
    22. import org.springframework.data.domain.Page;
    23. import org.springframework.data.domain.Pageable;
    24. import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
    25. import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
    26. import org.springframework.data.elasticsearch.core.query.SearchQuery;
    27. import org.springframework.stereotype.Service;
    28. import java.io.IOException;
    29. import java.util.ArrayList;
    30. import java.util.List;
    31. import java.util.UUID;
    32. import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
    33. @Service
    34. public class EsServiceImpl implements EsService {
    35. @Autowired
    36. private EsModelRepository esModelRepository;
    37. @Autowired
    38. private ElasticsearchRestTemplate elasticsearchRestTemplate;
    39. @Autowired
    40. private RestHighLevelClient client;
    41. @Override
    42. public AjaxResult searchES(String key, Pageable pageable) {
    43. Page<EsModel> ctContent = esModelRepository.findEsModelByCtContent(key, pageable);
    44. return AjaxResult.success(ctContent);
    45. }
    46. /***
    47. * 全文检索
    48. * @param key
    49. * @return
    50. */
    51. @Override
    52. public List<EsModel> searchWhole(String key, Pageable pageable) {
    53. //高亮字段设置
    54. String ctName = "ctName";
    55. String ctContent = "ctContent";
    56. String remark = "remark";
    57. String preTags = "color:#F56C6C\">";
    58. String postTags = "";
    59. HighlightBuilder.Field ctNameField = new HighlightBuilder.Field(ctName).preTags(preTags).postTags(postTags);
    60. HighlightBuilder.Field ctContentField = new HighlightBuilder.Field(ctContent).preTags(preTags).postTags(postTags);
    61. HighlightBuilder.Field remarkField = new HighlightBuilder.Field(remark).preTags(preTags).postTags(postTags);
    62. if (StringUtils.isEmpty(key)) {
    63. //throw new CustomException("请输入搜索内容!");
    64. List<EsModel> contentList = new ArrayList<>();
    65. return contentList;
    66. }
    67. //只要数据中包含就能检索到数据 (类似于模糊查询,有分词器的效果)
    68. //不同类别检索的进阶示例: https://www.cnblogs.com/jelly12345/p/14765477.html
    69. SearchQuery searchQuery = new NativeSearchQueryBuilder()
    70. .withPageable(pageable)//分页
    71. .withQuery(QueryBuilders.multiMatchQuery(key, "ctName", "ctContent", "remark"))
    72. .withHighlightFields(ctNameField, ctContentField, remarkField)//设置高亮
    73. // .withSort(SortBuilders.fieldSort("date").order(SortOrder.DESC))//排序
    74. .build();
    75. Page<EsModel> esModels = null;
    76. try {
    77. esModels = elasticsearchRestTemplate.queryForPage(searchQuery, EsModel.class, new HighlightResultMapper());
    78. }catch (Exception e){
    79. throw new CustomException("数据检索失败,请联系管理员处理!");
    80. }
    81. List<EsModel> contentList = esModels.getContent();
    82. return contentList;
    83. }
    84. /****
    85. *数据插入es中
    86. * @param esModel
    87. * @return
    88. */
    89. @Override
    90. public int insertEsModel(EsModel esModel) {
    91. try {
    92. esModel.setCtId(UUID.randomUUID().toString());
    93. EsModel save = esModelRepository.save(esModel);
    94. } catch (Exception e) {
    95. System.out.println("==================================错误信息是:"+e.getMessage()+"============================");
    96. throw new CustomException("ES数据新增失败,请联系管理员处理!");
    97. }
    98. return 1;
    99. }
    100. /***
    101. *es-update https://www.jb51.net/article/246798.htm
    102. * @param esModel
    103. * @return
    104. */
    105. @Override
    106. public int updateEsModel(EsModel esModel) {
    107. UpdateRequest updateRequest = new UpdateRequest(EsConstants.ES_INDEX, EsConstants.ES_INDEX_TYPE, String.valueOf(esModel.getCtId()));
    108. //更新 将对象转换为json
    109. updateRequest.doc(JSON.toJSONString(esModel), XContentType.JSON);
    110. //客户端发送请求,进行更新
    111. UpdateResponse update = null;
    112. try {
    113. update = client.update(updateRequest, RequestOptions.DEFAULT);
    114. } catch (IOException e) {
    115. throw new CustomException("ES数据同步失败可能原因是es中的业务ctId在数据库中不存在,请查看es客户端查询验证,请联系管理员处理!");
    116. }
    117. if (!"OK".equals(update.status().toString())) {
    118. throw new CustomException("ES数据修改失败,请联系管理员处理!");
    119. }
    120. return 1;
    121. }
    122. /***
    123. * 删除es中的数据
    124. * @param ctId
    125. * @return
    126. */
    127. @Override
    128. public int deleteById(String ctId) {
    129. try {
    130. esModelRepository.deleteById(ctId);
    131. }catch (Exception e){
    132. throw new CustomException("ES数据删除失败,请联系管理员处理!");
    133. }
    134. return 1;
    135. }
    136. }

    4.

    1. package com.admin.repository;
    2. import com.admin.model.EsModel;
    3. import org.springframework.data.domain.Page;
    4. import org.springframework.data.domain.Pageable;
    5. import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
    6. import org.springframework.stereotype.Repository;
    7. /**
    8. * @author wangwei
    9. * @date 2024-04-25 14:12:36
    10. */
    11. @Repository
    12. public interface EsModelRepository extends ElasticsearchRepository<EsModel, String> {
    13. /*****
    14. * 这儿查询的 findBy 根据idea 的补全查询(eg:ByCtContent 将查询es中的 字段名称为 ctContent 中的值)
    15. * @param ket
    16. * @param pageable
    17. * @return
    18. */
    19. Page<EsModel> findEsModelByCtContent(String ket, Pageable pageable);
    20. /****
    21. * 删除es操作
    22. */
    23. public void deleteById(Long id);
    24. }

    5.检索结果高亮显示

    1. package com.admin.util;
    2. import com.alibaba.fastjson.JSON;
    3. import org.elasticsearch.action.search.SearchResponse;
    4. import org.elasticsearch.search.SearchHit;
    5. import org.elasticsearch.search.SearchHits;
    6. import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
    7. import org.springframework.data.domain.Pageable;
    8. import org.springframework.data.elasticsearch.core.SearchResultMapper;
    9. import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
    10. import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
    11. import java.lang.reflect.Field;
    12. import java.util.ArrayList;
    13. import java.util.List;
    14. import java.util.Map;
    15. /***
    16. * 检索高亮设置
    17. * @author wangwei
    18. * @date 2024-04-25 11:55
    19. */
    20. public class HighlightResultMapper implements SearchResultMapper {
    21. @Override
    22. public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
    23. long totalHits = response.getHits().getTotalHits();
    24. List<T> list = new ArrayList<>();
    25. SearchHits hits = response.getHits();
    26. if (hits.getHits().length> 0) {
    27. for (SearchHit searchHit : hits) {
    28. Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
    29. T item = JSON.parseObject(searchHit.getSourceAsString(), clazz);
    30. Field[] fields = clazz.getDeclaredFields();
    31. for (Field field : fields) {
    32. field.setAccessible(true);
    33. if (highlightFields.containsKey(field.getName())) {
    34. try {
    35. field.set(item, highlightFields.get(field.getName()).fragments()[0].toString());
    36. } catch (IllegalAccessException e) {
    37. e.printStackTrace();
    38. }
    39. }
    40. }
    41. list.add(item);
    42. }
    43. }
    44. return new AggregatedPageImpl<>(list, pageable, totalHits);
    45. }
    46. @Override
    47. public <T> T mapSearchHit(SearchHit searchHit, Class<T> type) {
    48. return null;
    49. }
    50. }

    6.vue

    1. <template>
    2. <div class="app-container">
    3. <el-row :gutter="20">
    4. <!--用户数据-->
    5. <el-col :span="20" :xs="24">
    6. <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px" style="text-align: center">
    7. <el-form-item label="检索内容" prop="key" >
    8. <el-input
    9. v-model="queryParams.key"
    10. placeholder="请输入检索内容"
    11. clearable
    12. size="small"
    13. style="width: 240px"
    14. @keyup.enter.native="handleQuery"
    15. />
    16. </el-form-item>
    17. <el-form-item>
    18. <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
    19. <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
    20. </el-form-item>
    21. </el-form>
    22. <el-table v-loading="loading" :data="tableList" >
    23. <el-table-column label="编号" align="center" key="ctId" prop="ctId" v-if="columns[0].visible" />
    24. <el-table-column label="名称" align="center" key="ctName" prop="ctName" v-if="columns[1].visible" :show-overflow-tooltip="true" />
    25. <el-table-column label="内容" align="center" key="ctContent" prop="ctContent" v-if="columns[2].visible" :show-overflow-tooltip="true" />
    26. <el-table-column label="备注" align="center" key="remark" prop="remark" v-if="columns[2].visible" :show-overflow-tooltip="true" />
    27. </el-table>
    28. <pagination
    29. v-show="total>0"
    30. :total="total"
    31. :page.sync="queryParams.number"
    32. :limit.sync="queryParams.size"
    33. @pagination="getList"
    34. />
    35. </el-col>
    36. </el-row>
    37. </div>
    38. </template>
    39. <script>
    40. import { list, getWholeList, addEsModel, editEsModel, removeEsModel} from "@/api/search";
    41. import { getToken } from "@/utils/auth";
    42. import { treeselect } from "@/api/system/dept";
    43. import Treeselect from "@riophae/vue-treeselect";
    44. import "@riophae/vue-treeselect/dist/vue-treeselect.css";
    45. export default {
    46. name: "User",
    47. components: { Treeselect },
    48. data() {
    49. return {
    50. // 遮罩层
    51. loading: true,
    52. // 选中数组
    53. ids: [],
    54. // 非单个禁用
    55. single: true,
    56. // 非多个禁用
    57. multiple: true,
    58. // 显示搜索条件
    59. showSearch: true,
    60. // 总条数
    61. total: 0,
    62. // 表格数据
    63. tableList: [],
    64. // 弹出层标题
    65. title: "",
    66. // 部门树选项
    67. deptOptions: undefined,
    68. // 是否显示弹出层
    69. open: false,
    70. // 部门名称
    71. deptName: undefined,
    72. // 默认密码
    73. initPassword: undefined,
    74. // 日期范围
    75. dateRange: [],
    76. // 状态数据字典
    77. statusOptions: [],
    78. // 性别状态字典
    79. sexOptions: [],
    80. // 岗位选项
    81. postOptions: [],
    82. // 角色选项
    83. roleOptions: [],
    84. // 表单参数
    85. form: {},
    86. defaultProps: {
    87. children: "children",
    88. label: "label"
    89. },
    90. // 查询参数
    91. queryParams: {
    92. number: 1,
    93. size: 10,
    94. },
    95. // 列信息
    96. columns: [
    97. { key: 0, label: `编号`, visible: true },
    98. { key: 1, label: `名称`, visible: true },
    99. { key: 2, label: `内容`, visible: true },
    100. ],
    101. // 表单校验
    102. rules: {
    103. }
    104. };
    105. },
    106. watch: {
    107. },
    108. created() {
    109. this.getList();
    110. },
    111. methods: {
    112. /** 查询用户列表 */
    113. getList() {
    114. this.loading = true;
    115. console.log(this.queryParams)
    116. getWholeList(this.queryParams).then(response => {
    117. this.tableList = response.rows;
    118. this.total = response.total;
    119. this.loading = false;
    120. });
    121. },
    122. // 取消按钮
    123. cancel() {
    124. this.open = false;
    125. this.reset();
    126. },
    127. // 表单重置
    128. reset() {
    129. this.form = {
    130. ctId: undefined,
    131. ctName: undefined,
    132. ctContent: undefined,
    133. remark: undefined,
    134. };
    135. this.resetForm("form");
    136. },
    137. /** 搜索按钮操作 */
    138. handleQuery() {
    139. //this.queryParams.page = 1;
    140. this.getList();
    141. },
    142. /** 重置按钮操作 */
    143. resetQuery() {
    144. this.dateRange = [];
    145. this.resetForm("queryForm");
    146. this.handleQuery();
    147. },
    148. }
    149. };
    150. </script>

    7.

  • 相关阅读:
    阿里P8总结的Nacos入门笔记,从安装到进阶小白也能轻松学会
    C专家编程 第6章 运行的诗章:运行时数据结构 6.5 当函数被调用时发生了什么:过程活动记录
    GJB 5000B简介
    微服务环境搭建
    用于胰腺癌自动化综述报告和可切除性分类的大型语言模型| 文献速递-基于深度学习的乳房、前列腺疾病诊断系统
    如何利用curl仿造websocket请求?
    【C语言基础】:操作符详解(二)
    【快应用】如何跳转应用市场app详情页?
    BI业务分析思维:生产制造供应链订单交付优化分析三种方式
    代码随想录第46天|139.单词拆分,了解多重背包,背包总结
  • 原文地址:https://blog.csdn.net/weixin_41037490/article/details/138193246