当前位置:   article > 正文

Spring Boot集成Elasticsearch安装使用(详解)+ik分词器使用(详解)_springboot es 分词器

springboot es 分词器

目录

一、版本对应关系

二、Elasticsearch安装步骤

三、SpringBoot项目集成Elasticsearch

1.pom所需依赖

2.application项目配置文件

3.项目实体映射

4.持久层接口

5.持久层实现类

6.自定义查询方法

7.有可能出现的错误

1.-问题:Elasticsearch 与Spring Data与Lucene 等存在版本冲突

2.-解决方法:添加指定版本的lucene依赖而不使用默认的Elasticsearch自带的lucene

3.-实体映射Document注解规则

​编辑

4.-删除Elasticsearch索引库

四、Elasticsearch与ik分词器---用法

1.给Elasticsearch添加ik分词器

2.java项目直接测试分词效果

3.自定义一些词不让其进行分词


一、版本对应关系

(具有指导价值,但版本对应存在很高容错率)
1.Elasticsearch 7.6.2    SpringBoot2.5.6    (实现)

2.Elasticsearch 7.17.3   SpringBoot2.7.5    (实现)

二、Elasticsearch安装步骤

参考网址:https://blog.csdn.net/weixin_42633131/article/details/82902812

三、SpringBoot项目集成Elasticsearch

1.pom所需依赖

pom.xml

  1. <!--ES核心依赖-->
  2. <dependency>
  3.     <groupId>org.springframework.boot</groupId>
  4.     <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
  5. </dependency>
  6. <!--配置客户端需要的依赖,不存在添加,存在不添加-->
  7. <dependency>
  8.     <groupId>org.springframework.boot</groupId>
  9.     <artifactId>spring-boot-starter-web</artifactId>
  10. </dependency>
  11. <!--若不需要Tomcat,则只需要依赖spring-web-->
  12. <!--<dependency>
  13.     <groupId>org.springframework</groupId>
  14.     <artifactId>spring-web</artifactId>
  15. </dependency>-->

2.application项目配置文件

application.yml

  1. # yml配置elasticsearch客户端地址(可配置项有限)
  2. spring:
  3.   elasticsearch:
  4.     uris: http://127.0.0.1:9200    # elasticsearch 连接地址
  5.     #username: elastic # 用户名
  6.     #password: 123456 # 密码
  7.     connection-timeout: 10s # 连接超时时间(默认1s)
  8. socket-timeout: 30s # 数据读取超时时间(默认30s)

3.项目实体映射

  1. package com.nengyy.rest_server.elasticsearch.entity;
  2. import lombok.AllArgsConstructor;
  3. import lombok.Data;
  4. import lombok.NoArgsConstructor;
  5. import lombok.experimental.Accessors;
  6. import org.springframework.data.annotation.Id;
  7. import org.springframework.data.elasticsearch.annotations.Document;
  8. import org.springframework.data.elasticsearch.annotations.Field;
  9. import org.springframework.data.elasticsearch.annotations.FieldType;
  10. import java.io.Serializable;
  11. import java.math.BigDecimal;
  12. import java.util.Objects;
  13. @Data
  14. @Accessors(chain = true) // 支持链式set赋值功能
  15. @AllArgsConstructor // 自动生成包含全部参数的构造方法
  16. @NoArgsConstructor // 自动生成无参构造方法
  17. // @Document是SpringDataES标记实体类的注解
  18. // indexName指定关联的索引名称,运行时如果items索引不存在,SpringData会自动将它创建出来
  19. @Document(indexName = "items")
  20. public class ItemEfm implements Serializable {
  21. // SpringData标记当前属性为ES的主键
  22. @Id //ES本条数据ID(只能为long类型等转化为的String类型,不能出现数字之外的字母或汉字)(暂未研究解决方法)
  23. private Long id; //想用ES自带增删改查方法,此id需要为Long类型
  24. // SpringData标记title属性是text类型支持分词的,以及分词器
  25. @Field(type = FieldType.Keyword)
  26. private String GoodsId;
  27. @Field(type = FieldType.Text, //生成索引时使用 ik_max_word,在搜索时用ik_smart
  28. analyzer = "ik_max_word", //最细粒度拆分-->(字会重复被使用)(生成索引时,进行分词使用)
  29. searchAnalyzer = "ik_smart") //最粗粒度拆分-->智能拆分(字不会被重复使用)(搜索时,对搜索词进行分词)
  30. private String title; // 商品描述
  31. // Keyword类型是不需要分词的字符串类型
  32. @Field(type = FieldType.Keyword)
  33. private String category; // 商品分类
  34. @Field(type = FieldType.Keyword)
  35. private String brand; // 品牌(商品描述备用字段)(此字段用来做全称查询,用来补充分词查询的不足)
  36. @Field(type = FieldType.Keyword)
  37. private String price; // 价格
  38. @Field(type = FieldType.Keyword)
  39. private String origPrice; // 原价
  40. // 图片地址不会成为搜索条件,所以设置index = false
  41. // 这样ES就不会为它创建索引库了,能够节省空间
  42. @Field(type = FieldType.Keyword,index = false)
  43. private String imgPath; // 图片地址
  44. // images/1a123s-as4td-asdsa-jasbdjff.png
  45. @Field(type = FieldType.Keyword)
  46. private String intertestNum;//关注人数
  47. //重写equals,用于contains判断,非必要不会用到
  48. @Override
  49. public boolean equals(Object obj) {
  50. if (this == obj) return true;
  51. if (obj == null || getClass() != obj.getClass()) return false;
  52. ItemEfm other = (ItemEfm) obj;
  53. return Objects.equals(GoodsId, other.GoodsId) &&
  54. Objects.equals(title, other.title) &&
  55. Objects.equals(price, other.price) &&
  56. Objects.equals(origPrice, other.origPrice) &&
  57. Objects.equals(imgPath, other.imgPath) &&
  58. Objects.equals(intertestNum, other.intertestNum);
  59. }
  60. @Override
  61. public int hashCode() {
  62. return Objects.hash(GoodsId, title, price, origPrice, imgPath, intertestNum);
  63. }
  64. }

4.持久层接口

解析:持久层ItemRepository 接口继承extends ElasticsearchRepository 后,可以实现和MybatisPlus等同的作用

  1. package com.nengyy.rest_server.elasticsearch.repository;
  2. import com.nengyy.rest_server.elasticsearch.entity.ItemEfm;
  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. import java.util.List;
  8. // Spring 家族持久层命名规范为repository
  9. @Repository
  10. public interface ItemRepository extends ElasticsearchRepository<ItemEfm,Long>{
  11. // 当前ItemRepository接口可以继承SpringDataElasticsearch框架提供的父接口ElasticsearchRepository
  12. // 一旦继承,效果是会为指定的实体类自动生成基本的增删改查方法
  13. // ElasticsearchRepository<[关联的实体类名],[实体类主键类型]>
  14. // SpringData自定义查询
  15. // 遵循SpringData框架给定的格式,编写方法名称,就可以自动生成查询语句
  16. // query(查询): 表示当前方法是一个查询方法,类似sql中的select
  17. // Item\Items: 表示要查询的实体类,不带s返回单个对象,带s返回集合类型
  18. // By(通过): 标识开始设置条件的关键词,类似sql中的where
  19. // Title: 要查询的字段名称
  20. // Matches: 执行的查询操作,Matches表示执行查询支持分词的字符串 类似sql中的like
  21. Iterable<ItemEfm> queryItemsByTitleMatches(String title);
  22. // 四.es详细分词查询(多条件查询and)
  23. // 多条件查询
  24. // 多个条件之间需要使用逻辑运算符And或Or来分割
  25. // 方法参数赋值的依据是根据方法名称中参数的顺序来决定的(参数不能乱取名字,title,brand)
  26. Iterable<ItemEfm> queryItemsByTitleMatchesAndBrandMatches(String title, String brand);
  27. // 四.es详细分词查询(多条件排序查询or)
  28. // query、By、Matches、Or、OrderBy、Desc(倒序):均为关键字
  29. // Items :实体映射名字(也是此实体对应es其中一个索引库的名字)
  30. // Title、Brand :需要根据什么字段进行查询
  31. // Price :配合OrderBy、Desc意思是根据价格倒序
  32. Iterable<ItemEfm> queryItemsByTitleMatchesOrBrandMatchesOrderByPriceDesc(String title,String brand);
  33. // 一.全称查询(多写一个字段,对其设置FieldType.Keyword, 如此此字段就是不分词的全称索引)
  34. ItemEfm findByBrand(String brand);
  35. // 二.es精确分词查询(全称+分词+模糊三种查询合一)(精确查询,前端传参的分词与后端索引,必须全部匹配到才能查询到)
  36. org.springframework.data.domain.Page<ItemEfm> findByTitleOrderByIntertestNumDesc(String title,Pageable pageable);
  37. // 三.分页查询+分词查询--->分词查询(传参和索引都会进行分词,然后进行一一匹配,并通过自带算法做好排序)(自己也可以设置排序) (前端传参的分词与后端索引,只要能匹配到一个就能查询出来)
  38. // 实现分页查询:最后一个参数的位置添加声明类型Pageable的变量
  39. // 返回值修改为Page类型,这个类型的对象不但能够保存查询出的数据,而且还能自动计算出分页信息
  40. // 分页信息中包括:当前页,总页数,总条数,是否有上一页或下一页等
  41. Page<ItemEfm> queryItemsByTitleMatchesOrBrandMatchesOrderByIntertestNumDesc(
  42. String title,String brand,Pageable pageable);
  43. List<ItemEfm> queryItemsByTitleMatchesOrBrandMatchesOrderByOrigPriceDesc(String title,String brand);
  44. }

5.业务逻辑层实现类

  1. package com.nengyy.rest_server.service.impl.mall;
  2. import com.baomidou.mybatisplus.core.metadata.IPage;
  3. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  4. import com.nengyy.dao_mysql.common.utils.PageUtil;
  5. import com.nengyy.dao_mysql.mapper.primary.mall.CommodityListMapper;
  6. import com.nengyy.dem_common.utils.ListUtils;
  7. import com.nengyy.dem_common.utils.StringUtils;
  8. import com.nengyy.dto.mall.*;
  9. import com.nengyy.rest_server.elasticsearch.entity.ItemEfm;
  10. import com.nengyy.rest_server.elasticsearch.repository.ItemRepository;
  11. import com.nengyy.rest_server.service.impl.consignment.DatacenterIdGenerator;
  12. import com.nengyy.rest_server.service.mall.ItemRepositoryService;
  13. import org.springframework.beans.factory.annotation.Autowired;
  14. import org.springframework.data.domain.PageRequest;
  15. import org.springframework.stereotype.Service;
  16. import java.util.*;
  17. /**
  18. * @Author: cyz
  19. * @Date: 2023/04/24
  20. * @Description:
  21. */
  22. @Service
  23. public class ItemRepositoryServiceImpl implements ItemRepositoryService {
  24. private final ItemRepository itemRepository;
  25. private final CommodityListMapper commodityListMapper;
  26. @Autowired
  27. public ItemRepositoryServiceImpl(ItemRepository itemRepository, CommodityListMapper commodityListMapper) {
  28. this.itemRepository = itemRepository;
  29. this.commodityListMapper = commodityListMapper;
  30. }
  31. /**从数据库查出所有符合条件的商品 , 每天定时进行es索引的刷新*/
  32. @Override
  33. public String goodsList() {
  34. List<ESCommodityListDto> data = commodityListMapper.getGoodsList();
  35. List<ItemEfm> list = new ArrayList<>();
  36. DatacenterIdGenerator snowId1 = new DatacenterIdGenerator(17,18);//获取雪花算法ID
  37. ItemEfm item;
  38. if(data != null){
  39. for (ESCommodityListDto listDto:data) {
  40. if("2".equals(listDto.getGoodsSource())){
  41. item = new ItemEfm();
  42. item.setId(snowId1.nextId());
  43. item.setGoodsId(listDto.getGoodsId());
  44. item.setTitle(listDto.getGoodsDesc());
  45. item.setCategory(listDto.getGoodsType());
  46. item.setBrand(listDto.getGoodsDesc()); //此字段用来做全称查询,用来补充分词查询的不足
  47. item.setPrice(listDto.getGoodsFee());
  48. item.setOrigPrice(listDto.getReservFee1());
  49. item.setImgPath(listDto.getFilePath());
  50. item.setIntertestNum(listDto.getIntertestNum());
  51. list.add(item);
  52. }else{
  53. item = new ItemEfm();
  54. item.setId(snowId1.nextId());
  55. item.setGoodsId(listDto.getGoodsId());
  56. item.setTitle(listDto.getGoodsName());
  57. item.setCategory(listDto.getGoodsType());
  58. item.setBrand(listDto.getGoodsName()); //此字段用来做全称查询,用来补充分词查询的不足
  59. item.setPrice(listDto.getGoodsFee());
  60. item.setOrigPrice(listDto.getReservFee1());
  61. item.setImgPath(listDto.getFilePath());
  62. item.setIntertestNum(listDto.getIntertestNum());
  63. list.add(item);
  64. }
  65. }
  66. //先删除之前存的索引(批量删)
  67. itemRepository.deleteAll();
  68. //添加新的索引 (批量加)
  69. itemRepository.saveAll(list);
  70. }
  71. return "成功";
  72. }
  73. /**
  74. * Es搜索出的商品(分页获取商品列表)
  75. * @param in
  76. * @return
  77. */
  78. @Override
  79. public Page<CommodityListDto> searchCommodityList(SiftEsCommodityListDto in) {
  80. //一.全称查询(不分词查询)
  81. ItemEfm oneGoods = itemRepository.findByBrand(in.getGoodsDesc());
  82. //二.es精确分词查询(全称+分词+模糊三种查询合一)(精确查询,前端传参的分词与后端索引,必须全部匹配到才能查询到)
  83. org.springframework.data.domain.Page<ItemEfm> pageGoodsList = itemRepository.findByTitleOrderByIntertestNumDesc(in.getGoodsDesc(),PageRequest.of(0, 49));
  84. //三.分页查(非精确分词查询)(前端传参的分词与后端索引,只要能匹配到一个就能查询出来)
  85. int size = in.getPageSize() - pageSizeExtra;
  86. int size1 = size >=0 ? size :1;
  87. org.springframework.data.domain.Page<ItemEfm> page = itemRepository
  88. .queryItemsByTitleMatchesOrBrandMatchesOrderByIntertestNumDesc( //通过商品描述和商品品牌(暂定传值为空)进行查询并通过关注人数进行排序
  89. in.getGoodsDesc(),"",PageRequest.of(in.getPageNo() - 1, size1));
  90. }

6.自定义查询方法

Spring Data根据方法名称自动实现功能:

查询方式两种:query(详细查询)与find(精确查询)


// 四.es详细分词查询(多条件排序查询or)

    // query、By、Matches、Or、OrderBy、Desc(倒序):均为关键字

    // Items :实体映射名字(也是此实体对应es其中一个索引库的名字)

    // Title、Brand :需要根据什么字段进行查询

    // Price :配合OrderBy、Desc意思是根据价格倒序

    //黑色和蓝色均为关键字   实体映射名 根据哪个字段查询                 根据哪个字段倒序

Iterable<ItemEfm> queryItemsByTitleMatchesOrBrandMatchesOrderByPriceDesc(String title,String brand);

// 二.es精确分词查询(全称+分词+模糊三种查询合一)(精确查询,前端传参的分词与后端索引,必须全部匹配到才能查询到)

    org.springframework.data.domain.Page<ItemEfm>  findByTitleOrderByIntertestNumDesc(String title,Pageable pageable);

// 三.分页查询+分词查询--->分词查询(传参和索引都会进行分词,然后进行一一匹配,并通过自带算法做好排序)(自己也可以设置排序) (前端传参的分词与后端索引,只要能匹配到一个就能查询出来)

// 实现分页查询:最后一个参数的位置添加声明类型Pageable的变量

// 返回值修改为Page类型,这个类型的对象不但能够保存查询出的数据,而且还能自动计算出分页信息

// 分页信息中包括:当前页,总页数,总条数,是否有上一页或下一页等

    Page<ItemEfm> queryItemsByTitleMatchesOrBrandMatchesOrderByIntertestNumDesc(

            String title,String brand,Pageable pageable);

7.有可能出现的错误

1.-问题:Elasticsearch 与Spring Data与Lucene 等存在版本冲突

2.-解决方法:添加指定版本的lucene依赖而不使用默认的Elasticsearch自带的lucene

可以通过chatGpt自行问Elasticsearch不同版本对应的lucene版本

<dependency>

    <groupId>org.apache.lucene</groupId>

    <artifactId>lucene-core</artifactId>

    <version>8.11.1</version>

</dependency>

3.-实体映射Document注解规则

@Document(indexName = "itemsapp1")       

//其中itemsapp1是自定义的索引库的库名,es中有很多的索引库,是项目通过不同实体创建的索引库

4.-删除Elasticsearch索引库

解释:(删除索引后,重启项目,调用刷新索引项目可以重建索引库)

解决方法:1.想删除Elasticsearch索引库,可以使用es的可视化工具

2.Elasticvue -(es的可视化工具)用于浏览器的免费开源 Elasticsearch GUI

Elasticvue安装步骤网址:https://blog.csdn.net/UbuntuTouch/article/details/125777834

3.利用Elasticvue连接上Elasticsearch

四、Elasticsearch与ik分词器---用法

1.给Elasticsearch添加ik分词器

--Ik下载网址: https://github.com/medcl/elasticsearch-analysis-ik/releases

--参考ik详解网址:【精选】ElasticSearch——IK分词器的下载及使用_ik分词器下载-CSDN博客

--将解压的ik分词器改名为ik,放到plugins目录下即可(下之前百度查自己es对应版本的ik,容错率挺高的)

2.java项目直接测试分词效果

1.案例代码

GET http://localhost:9200

### 三个#既是分隔符也是注释,两个请求之间必须使用它来分割,否则无法运行

POST http://localhost:9200/_analyze

Content-Type: application/json

{

  "text": "绿色冰种手镯",

  "analyzer": "ik_smart"

}

2.创建一个demo案例

3.Es启动后,直接点击启动就可以测试

3.自定义一些词不让其进行分词

1.直接用记事本打开main.dic,在里面添加不想进行分词的词语

2.ik_smart和ik_max_word两种分词不同

ik_smart      //智能分词: 粗粒度分词 (字不会被重复使用)

ik_max_word   //细粒度分词          (字会重复被使用)
项目实体建议:

    @Field(type = FieldType.Text,                    //生成索引时使用 ik_max_word,在搜索时(对前端传递来的参数分词)用ik_smart

                    analyzer = "ik_max_word",      //最细粒度拆分-->(字会重复被使用)(生成索引时,进行分词使用)

                    searchAnalyzer = "ik_smart")    //最粗粒度拆分-->智能拆分(字不会被重复使用)(搜索时,对搜索词进行分词)

    private String title;       // 商品描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/860245
推荐阅读
相关标签
  

闽ICP备14008679号