Java操作Elasticsearch的实用指南

news2024/12/23 0:46:51

Java操作Elasticsearch的实用指南

  • 一、创建索引
  • 二、增删改查

一、创建索引

在ElasticSearch中索引相当于mysql中的表,mapping相当于表结构,所以第一步我们要先创建索引。

  • 假设我们有一张文章表的数据需要同步到ElasticSearch,首先需要根据数据库表创建ES的索引结构。
-- 文章表
create table if not exists post
(
    id         bigint auto_increment comment 'id' primary key,
    title      varchar(512)                       null comment '标题',
    content    text                               null comment '内容',
    tags       varchar(1024)                      null comment '标签列表(json 数组)',
    thumbNum   int      default 0                 not null comment '点赞数',
    favourNum  int      default 0                 not null comment '收藏数',
    userId     bigint                             not null comment '创建用户 id',
    createTime datetime default CURRENT_TIMESTAMP not null comment '创建时间',
    updateTime datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
    isDelete   tinyint  default 0                 not null comment '是否删除',
    index idx_userId (userId)
) comment '帖子' collate = utf8mb4_unicode_ci;

ElasticSearch的索引结构:

  • aliases:别名(为了方便后续数据迁移)
  • 字段类型是text,这个字段可以被分词,可模糊查询;字段类型是keyword,只能完全匹配,精确查询。
  • analyzer(存储时生效的分词器):用ik_max_word,拆的更碎、索引更多,更有可能被搜出来
  • search analyzer (查询时生效的分词器):用ik_smart,更偏向于用户想要搜的分词。
PUT post
{
  "aliases": {
    "post": {}
  },
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "ik_max_word",
        "search_analyzer": "ik_smart",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "content": {
        "type": "text",
        "analyzer": "ik_max_word",
        "search_analyzer": "ik_smart",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "tags": {
        "type": "keyword"
      },
      "userId": {
        "type": "keyword"
      },
      "createTime": {
        "type": "date"
      },
      "updateTime": {
        "type": "date"
      },
      "isDelete": {
        "type": "keyword"
      }
    }
  }
}

在这里插入图片描述

二、增删改查

使用java客户端进行增删改查,第一步导入依赖。

 <!-- elasticsearch-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
  • 第一种方式: ElasticsearchRepository<PostEsDTO,Long>,默认提供了简单的增删改查,多用于可预期的、相对没那么复杂的查询、自定义查询。
    在这里插入图片描述
   @Test
    void testSelect() {
        System.out.println(postEsDao.count());
        Page<PostEsDTO> PostPage = postEsDao.findAll(
                PageRequest.of(0, 5, Sort.by("createTime")));
        List<PostEsDTO> postList = PostPage.getContent();
        System.out.println(postList);
    }

    @Test
    void testAdd() {
        PostEsDTO postEsDTO = new PostEsDTO();
        postEsDTO.setId(1L);
        postEsDTO.setTitle("我是章三");
        postEsDTO.setContent("张三学习java,学习使我快乐!");
        postEsDTO.setTags(Arrays.asList("java", "python"));
        postEsDTO.setUserId(1L);
        postEsDTO.setCreateTime(new Date());
        postEsDTO.setUpdateTime(new Date());
        postEsDTO.setIsDelete(0);
        postEsDao.save(postEsDTO);
        System.out.println(postEsDTO.getId());
    }

    @Test
    void testFindById() {
        Optional<PostEsDTO> postEsDTO = postEsDao.findById(1L);
        System.out.println(postEsDTO);
    }

    @Test
    void testCount() {
        System.out.println(postEsDao.count());
    }

    @Test
    void testFindByCategory() {
        List<PostEsDTO> postEsDaoTestList = postEsDao.findByUserId(1L);
        System.out.println(postEsDaoTestList);
    }

ES 中,_开头的字段表示系统默认字段,比如 _id,如果系统不指定,会自动生成。但是不会在surce 字段中补充 id 的值,所以建议大家手动指定。

支持根据方法名自动生成方法,比如:

ListcPostEsDTO> findByTitle(String title);
  • 第二种方式: Spring 默认给我们提供的提作 es 的客户端对象 ElasticsearchRestTemplate,也提供了增制改查,它的增删改查更灵活,适用于更复杂的操作。
    ES的搜索条件:
GET /_search
{
  "query": { 
    "bool": {   组合条件
      "must": [   必须都满足
        { "match": { "title":   "Search"  }},   模糊查询   
        { "match": { "content": "Elasticsearch" }}
      ],
      "filter": [ 
        { "term":  { "status": "published" }},  精确查询
        { "range": { "publish_date": { "gte": "2015-01-01" }}}  范围查询
      ],
      "should" : [
        { "term" : { "tags" : "env1" } },
        { "term" : { "tags" : "deployed" } }
      ],
      "minimum_should_match" : 1,   包含匹配,最少匹配1"boost" : 1.0
    }
  }
}

对于复杂的查询,建议使用第二种方式。

//依赖注入
@Resource
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

三个步骤:
1、取参数
2、把参数组合为ES支持的搜索条件
3、从返回值中取结果

       Long id = postQueryRequest.getId();
        Long notId = postQueryRequest.getNotId();
        String searchText = postQueryRequest.getSearchText();
        String title = postQueryRequest.getTitle();
        String content = postQueryRequest.getContent();
        List<String> tagList = postQueryRequest.getTags();
        List<String> orTagList = postQueryRequest.getOrTags();
        Long userId = postQueryRequest.getUserId();
        // es 起始页为 0
        long current = postQueryRequest.getCurrent() - 1;
        long pageSize = postQueryRequest.getPageSize();
        String sortField = postQueryRequest.getSortField();
        String sortOrder = postQueryRequest.getSortOrder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        // 过滤
        boolQueryBuilder.filter(QueryBuilders.termQuery("isDelete", 0));
        if (id != null) {
            boolQueryBuilder.filter(QueryBuilders.termQuery("id", id));
        }
        if (notId != null) {
            boolQueryBuilder.mustNot(QueryBuilders.termQuery("id", notId));
        }
        if (userId != null) {
            boolQueryBuilder.filter(QueryBuilders.termQuery("userId", userId));
        }
        // 必须包含所有标签
        if (CollectionUtils.isNotEmpty(tagList)) {
            for (String tag : tagList) {
                boolQueryBuilder.filter(QueryBuilders.termQuery("tags", tag));
            }
        }
        // 包含任何一个标签即可
        if (CollectionUtils.isNotEmpty(orTagList)) {
            BoolQueryBuilder orTagBoolQueryBuilder = QueryBuilders.boolQuery();
            for (String tag : orTagList) {
                orTagBoolQueryBuilder.should(QueryBuilders.termQuery("tags", tag));
            }
            orTagBoolQueryBuilder.minimumShouldMatch(1);
            boolQueryBuilder.filter(orTagBoolQueryBuilder);
        }
        // 按关键词检索
        if (StringUtils.isNotBlank(searchText)) {
            boolQueryBuilder.should(QueryBuilders.matchQuery("title", searchText));
          //  boolQueryBuilder.should(QueryBuilders.matchQuery("description", searchText));
            boolQueryBuilder.should(QueryBuilders.matchQuery("content", searchText));
            boolQueryBuilder.minimumShouldMatch(1);
        }
        // 按标题检索
        if (StringUtils.isNotBlank(title)) {
            boolQueryBuilder.should(QueryBuilders.matchQuery("title", title));
            boolQueryBuilder.minimumShouldMatch(1);
        }
        // 按内容检索
        if (StringUtils.isNotBlank(content)) {
            boolQueryBuilder.should(QueryBuilders.matchQuery("content", content));
            boolQueryBuilder.minimumShouldMatch(1);
        }
        // 排序
        SortBuilder<?> sortBuilder = SortBuilders.scoreSort();
        if (StringUtils.isNotBlank(sortField)) {
            sortBuilder = SortBuilders.fieldSort(sortField);
            sortBuilder.order(CommonConstant.SORT_ORDER_ASC.equals(sortOrder) ? SortOrder.ASC : SortOrder.DESC);
        }
        // 分页
        PageRequest pageRequest = PageRequest.of((int) current, (int) pageSize);
        // 构造查询
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(boolQueryBuilder)
                .withPageable(pageRequest).withSorts(sortBuilder).build();
        SearchHits<PostEsDTO> searchHits = elasticsearchRestTemplate.search(searchQuery, PostEsDTO.class);

后记
👉👉💕💕美好的一天,到此结束,下次继续努力!欲知后续,请看下回分解,写作不易,感谢大家的支持!! 🌹🌹🌹

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2114589.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DisplayManagerService启动及主屏添加-Android13

DisplayManagerService启动及主屏添加-Android13 1、DisplayManagerService启动1.1 简要时序图 2、DEFAULT_DISPLAY主屏幕添加2.1 物理屏热插拔监听2.2 物理屏信息 3、默认屏幕亮度 1、DisplayManagerService启动 1.1 简要时序图 代码位置&#xff1a;frameworks/base/service…

git:基本操作(2)

目录 git操作&#xff08;2&#xff09; 1.版本回退 2.撤销修改 3.删除文件 git操作&#xff08;2&#xff09; 1.版本回退 git能够管理文件的历史版本&#xff0c;这也是版本控制器的重要能力&#xff0c;因此&#xff0c;git也提供了版本回退这样的功能。 执行git reset…

QT6聊天室项目 网络通信实现逻辑分析

实现逻辑 模块话网络通信设计分析 NetClient类 功能&#xff1a;负责与服务器进行通信httpClient:处理HTTP请求websocketClient&#xff1a;处理WebSocket通信 HTTP请求封装 设计请求和服务器响应的接口设计函数测试网络连接性设计处理的函数处理HTTP请求&#xff08;后期实现…

C#/.NET/.NET Core推荐学习路线文档文章

前言 专门为C#/.NET/.NET Core推荐学习路线&文档&文章提供的一个Issues&#xff0c;各位小伙伴可以把自己觉得不错的学习路线、文档、文章相关地址分享出来&#x1f91e;。 https://github.com/YSGStudyHards/DotNetGuide/issues/10 &#x1f3f7;️C#/.NET/.NET Cor…

智慧工地解决方案-2

### 1. 智慧工地解决方案概述 《智慧工地解决方案》针对传统工地的低效率和高风险问题&#xff0c;提出了一套集成现代技术的智能管理系统&#xff0c;以提升工地安防和生产效率。 ### 2. 工地现状与挑战 当前工地存在安全意识薄弱、管理粗放、环境污染监测困难等问题&#…

数据分析面试题:客户投保问题分析

目录 0 场景描述 1 数据准备 2 问题分析 2.1 计算小微公司的平均经营时长 2.2 计算小微公司且角色为投保人,保险起期在18年的总保费 2.3 假设,DWD_CUSTOMER_REL客户关联关系表中,存在部分客户保单数很多,部分客户保单数很少的情况,此时DWD_CUSTOMER_BASE表关联,程序…

Learn ComputeShader 10 HUD Overlay

前言&#xff1a; 1. HUD Overlay (Head-Up Display Overlay) 定义: HUD 是指游戏或应用程序中的一类叠加界面元素&#xff0c;通常显示在屏幕上&#xff0c;用于向用户提供实时信息。它通常显示关键信息而不会打断用户的主要活动或视线。应用场景: 常见于游戏、飞行模拟器和…

[项目][CMP][Page Cache]详细讲解

目录 1.申请内存2.释放内存3.框架 1.申请内存 当Central Cache向Page Cache申请内存时&#xff0c;Page Cache先检查对应位置有没有span&#xff0c;如果没有则向更大页寻找一个span&#xff0c;如果找到则分裂成两个 比如&#xff1a;申请的是4页page&#xff0c;4页page后面…

【MRI基础】TI反转时间概念

在磁共振成像 (MRI) 中&#xff0c;反转时间 (TI) 是反转恢复脉冲序列中的一个特定参数。它表示施加 180 度反转脉冲&#xff08;将纵向磁化翻转到相反方向&#xff09;与随后的 90 度激励脉冲&#xff08;将磁化翻转到横向平面以创建 MR 信号&#xff09;之间的时间间隔。 MRI…

常见概念 -- 电层业务调制谱宽与光层通道谱宽

本文介绍了“电层业务调制谱宽”和“光层通道谱宽”这两个概念&#xff0c;并结合网管的配置界面解释二者的配置方法。 电层业务调制谱宽 电层业务调制谱宽与光线路码型唯一相关&#xff0c;光线路码型确定后谱宽随之确定。 电层业务调制谱宽是指某业务信号的损耗谱从峰值下…

C++解决:求排列数

描述 输入两个整数m,n&#xff0c;求m个数字中选n个数的排列数。&#xff08;1<n<m<50&#xff09; 输入描述 两个正整数m和n。 输出描述 一个正整数表示排列数。 用例输入 1 6 5 用例输出 1 720 AC code #include<bits/stdc.h> using namespace s…

[linux 驱动]platform总线设备驱动详解与实战

目录 1 描述 2 结构体 2.1 bus_type 2.2 platform_bus_type 2.2.1 platform_match 2.2.2 platform_uevent 2.2.3 platform_dma_configure 2.2.4 platform_dev_pm_ops 2.3 platform_driver 2.4 platform_device 3 platform注册 3.1 platform_driver_register 3.1.1 …

【python因果推断库11】工具变量回归与使用 pymc 验证工具变量4

目录 Wald 估计与简单控制回归的比较 CausalPy 和 多变量模型 感兴趣的系数 复杂化工具变量公式 Wald 估计与简单控制回归的比较 但现在我们可以将这个估计与仅包含教育作为控制变量的简单回归进行比较。 naive_reg_model, idata_reg make_reg_model(covariate_df.assign…

C语言:刷题日志(1)

一.阶乘计算升级版 本题要求实现一个打印非负整数阶乘的函数。 其中n是用户传入的参数&#xff0c;其值不超过1000。如果n是非负整数&#xff0c;则该函数必须在一行中打印出n!的值&#xff0c;否则打印“Invalid input”。 首先&#xff0c;知道阶乘是所有小于及等于该数的…

halcon 自定义距离10的一阶导数幅图,摆脱sobel的3掩码困境

一&#xff0c;为什么要摆脱3的掩码 在处理图像的过程中&#xff0c;会用到平滑算子&#xff0c;很容易破坏边际&#xff0c;所谓的一阶导数sobel只计算掩码为3的差分&#xff0c;在幅度图分割中&#xff0c;往往是很难把握的。 举个例子-现在图像头平滑好了&#xff0c;缺陷…

【Python 千题 —— 算法篇】寻找两个正序数组的中位数

Python 千题持续更新中 …… 脑图地址 &#x1f449;&#xff1a;⭐https://twilight-fanyi.gitee.io/mind-map/Python千题.html⭐ 题目背景 在处理大规模数据时&#xff0c;我们经常需要对数据进行排序和分析。一个常见问题是如何高效地从两个正序数组中找出它们的中位数。…

今天又学到了——图编号关联章节号,QGIS下载文件存储的瓦片

记录教程来源&#xff1a;​​​​​​【Word图编号关联章节号】图片分章节 编号&#xff0c;图1-1、图2-1_哔哩哔哩_bilibili 上面链接这个实现的是这个效果&#xff1a; word自动目录及章节自动编号教程_哔哩哔哩_bilibili&#xff0c;这个的效果是自己设计多级列表&#xf…

Pr:首选项 - 音频

Pr菜单&#xff1a;编辑/首选项 Edit/Preferences Premiere Pro 首选项中的“音频” Audio选项卡主要作用是控制音频的处理设置&#xff0c;包括音量调整、波形生成、音频渲染等选项&#xff0c;这些设置有助于优化音频的处理和编辑工作&#xff0c;适用于不同的剪辑需求和项目…

【Qt】Qt与Html网页进行数据交互

前言&#xff1a;此项目使用达梦数据库&#xff0c;以Qt制作服务器&#xff0c;Html制作网页客户端界面&#xff0c;可以通过任意浏览器访问。 1、Qt与网页进行数据交互 1.1、第一步&#xff1a;准备qwebchannel.js文件 直接在qt的安装路径里复制即可 1.2、第二步&#xf…

海外云手机是否适合运营TikTok?

随着科技的迅猛发展&#xff0c;海外云手机逐渐成为改变工作模式的重要工具。这种基于云端技术的虚拟手机&#xff0c;不仅提供了更加便捷、安全的使用体验&#xff0c;还在电商引流和海外社媒管理等领域展示了其巨大潜力。那么&#xff0c;海外云手机究竟能否有效用于运营TikT…