springboot整合elasticsearch7

springboot整合elasticsearch7版本 elasticsearc 17 jdk8 父工程依赖 lt properties gt lt spring boot version gt 2 3 12 RELEASE spring boot version properties lt dependencies

大家好,我是讯享网,很高兴认识大家。

版本:elasticsearch7.17,jdk8

父工程依赖

<properties> <spring-boot.version>2.3.12.RELEASE</spring-boot.version> </properties> <dependencies> <!--注意:由于 spring-boot-starter-web 默认替我们引入了核心启动器 spring-boot-starter, 因此,当 Spring Boot 项目中的 pom.xml 引入了 spring-boot-starter-web 的依赖后, 就无须在引入 spring-boot-starter 核心启动器的依赖了--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.3.12.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <version>2.3.12.RELEASE</version> <scope>test</scope> </dependency> <dependency> <groupId>com.meng</groupId> <artifactId>service</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.16</version> <scope>compile</scope> </dependency> </dependencies> 

讯享网

子工程依赖

讯享网<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <version>${spring-boot.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> <version>${spring-boot.version}</version> </dependency> </dependencies> 

application.yml(新版springboot2.3.12使用此配置,本文基于此版本)

spring: elasticsearch: rest: uris: 192.168.233.134:9200 

application.yml(旧版springboot2.1.6使用此配置)

讯享网spring: data: elasticsearch: cluster-nodes: 192.168.233.134:9300 

启动类

@SpringBootApplication public class EsApplication { 
    public static void main(String[] args) { 
    SpringApplication.run(EsApplication.class , args); } } 

实体类(es7中创建索引方式好像变了,这里行不通了)

讯享网@Data @Document(indexName = "goods" , shards = 3 , replicas = 0) public class Goods { 
    @Id private Integer id; @Field(type = FieldType.Text , analyzer = "ik_max_word") private String name; @Field(type = FieldType.Keyword) private String category; @Field(type = FieldType.Keyword) private String images; @Field(type = FieldType.Integer) private Integer price; } 

Spring Data通过注解来声明字段的映射属性,有下面的三个注解:

  1. @Document 作用在类,标记实体类为文档对象,一般有四个属性
    indexName:对应索引库名称 type:对应在索引库中的类型 shards:分片数量,默认5 replicas:副本数量,默认1 
  2. @Id 作用在成员变量,标记一个字段作为id主键
  3. @Field 作用在成员变量,标记为文档的字段,并指定字段映射属性:
    讯享网type:字段类型,取值是枚举:FieldType index:是否索引,布尔类型,默认是true store:是否存储,布尔类型,默认是false analyzer:分词器名称:ik_max_word 

Repository

public interface EsRepository extends ElasticsearchRepository<User, Integer> { 
    } 

ElasticsearchTemplate、ElasticsearchRepository、ElasticsearchRestTemplate区别

ElasticsearchRepository可以做Elasticsearch的相关数据的增删改查,用法和普通的接口是一样的,这样就能统一ElasticSearch和普通的JPA操作,获得和操作mysql一样的代码体验。同时也可以看到ElasticsearchRepository的功能是比较少的,简单查询够用,但复杂查询就稍微显得力不从心了。
ElasticsearchRepository继承自PagingAndSortingRepository,PagingAndSortingRepository又继承CrudRepository
ElasticsearchRepository中的方法基本都过时了
在这里插入图片描述
讯享网
PagingAndSortingRepository中的两个方法,排序和分页

讯享网@NoRepositoryBean public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> { 
    / * Returns all entities sorted by the given options. * * @param sort * @return all entities sorted by the given options */ Iterable<T> findAll(Sort sort); / * Returns a {@link Page} of entities meeting the paging restriction provided in the {@code Pageable} object. * * @param pageable * @return a page of entities */ Page<T> findAll(Pageable pageable); } 

CrudRepository中的方法就是简单的增删查改
在这里插入图片描述
详见es中ElasticsearchRepository 的原理和使用

ElasticsearchTemplate 则提供了更多的方法,同时也包括分页之类的,他其实就是一个封装好的ElasticSearch Util功能类,通过直接连接client来完成数据的操作
在这里插入图片描述
详见es中ElasticSearchTemplate类的实现原理及使用

ElasticsearchRestTemplate 在新版的SpringBoot项目中,在这个包下,推荐使用的是ElasticsearchRestTemplate这个类(ElasticsearchTemplate不推荐使用了),和之前的用法有些不同。
本文使用springboot版本:2.3.12
在这里插入图片描述

参考:ElasticsearchRestTemplate使用

创建索引

@Test public void testIndex(){ 
    boolean goods = template.indexOps(Goods.class).create();//新版本用这个方法 boolean goods1 = template.createIndex(User.class); // 此方法已过时 System.out.println("goods = " + goods); } 

结果
在这里插入图片描述

现在新版的API创建的索引没有mapping了,两种方式解决这个问题

1、插入数据时使用默认生成的mapping(不推荐)
[外链图片转存失败,源站可能有防盗在这里插入!链机制,建描述]议将图片上https://传(imbMOhjlog.csdnimg.cn/18e28d59bae64590a955668922a940bf.png)https://img-blog.csdnim自动g.cn/1ae68e28d59b4590a955668922a940bf.png)]
这种方式生成的mapping字段的type并不是和实体类上用@Field声明的一致,而是自己生成的默认的。

2、已创建的索引,设置mapping

讯享网 / * 如果已经创建了index,可用此方法设置mapping */ @Test public void testCreateIndexWithoutIndex(){ 
    IndexCoordinates indexCoordinates = IndexCoordinates.of("phone");//已创建的索引 // 根据索引实体,获取mapping字段 Document mapping = restTemplate.indexOps(indexCoordinates).createMapping(Phone.class); // 创建索引mapping restTemplate.indexOps(indexCoordinates).putMapping(mapping); } 

这种方式生成的mapping就是实体类中用@Field声明的类型了

在这里插入图片描述

还可以使用外部json文件方式创建索引

把setting放到项目中的一个文件中
在这里插入图片描述
phone_setting.json

{
  "index": {
    "max_result_window": "500000",
    "analysis": {
      "filter": {
        "limit_len": {
          "type": "length",
          "min": "1"
        }
      },
      "analyzer": {
        "ik_max_custom": {
          "filter": [
            "limit_len"
          ],
          "char_filter": [
            "html_strip"
          ],
          "tokenizer": "ik_max_word"
        },
        "ik_smart_custom": {
          "type":      "custom",
          "tokenizer": "ik_smart",
          "char_filter": [],
          "filter": [
            "limit_len"
          ]
        },
        "default_pattern_analyzer": {
          "type":"pattern"
        }
      }
    }
  }
}
讯享网@Autowired private ElasticsearchRestTemplate restTemplate; @Value("classpath:phone_setting.json") private Resource esSetting; @Test public void testCreateIndex() throws Exception{ 
    IndexCoordinates indexCoordinates = IndexCoordinates.of("phone"); // 根据索引实体,获取mapping字段 Document mapping = restTemplate.indexOps(indexCoordinates).createMapping(Phone.class); // 创建索引 // 读取setting配置文件 String esSettingStr = IOUtils.toString(esSetting.getInputStream(), Charset.forName("utf-8")); // setting Document setting = Document.parse(esSettingStr); restTemplate.indexOps(indexCoordinates).create(setting); // 创建索引mapping restTemplate.indexOps(indexCoordinates).putMapping(mapping); } 

可以参考这里es7创建索引

插入数据

 @Autowired private PhoneRepository phoneRepository; //插入数据 @Test public void testSave(){ 
    Phone phone = new Phone(1 , "诺基亚5300" , "诺基亚"); restTemplate.save(phone); } //批量插入数据 @Test public void testBatchSave(){ 
    List<Phone> list = new ArrayList<>(); Phone phone2 = new Phone(2 , "小米12pro" , "小米"); Phone phone3 = new Phone(3 , "iphone12" , "苹果"); list.add(phone2); list.add(phone3); phoneRepository.saveAll(list); } 

修改数据

再插入一遍,只要id一致,就是修改

讯享网 //修改数据 @Test public void testUpdate(){ 
    Phone phone3 = new Phone(3 , "iphonese 3" , "苹果"); restTemplate.save(phone3); } 

删除数据

删除数据的方法就比较多了

 //删除数据 @Test public void testDelete(){ 
    Phone phone3 = new Phone(3 , "iphonese 3" , "苹果"); String delete = restTemplate.delete(phone3); System.out.println("delete = " + delete);//delete = 3 } //删除数据2 @Test public void testDelete2(){ 
    String delete = restTemplate.delete("3" , Phone.class); System.out.println("delete = " + delete);//delete = 3 } //删除数据3 @Test public void testDelete3(){ 
    phoneRepository.deleteById(2); } //删除id大于20的goods数据 @Test public void test0DeleteByQueryBuilder(){ 
    RangeQueryBuilder id = QueryBuilders.rangeQuery("id").gt(20); NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(id).build(); template.delete(query , Goods.class , IndexCoordinates.of("goods")); } 

在这里插入图片描述

查询数据

重点就在查询了

简单查询

讯享网 //查询全部 @Test public void testQuery(){ 
    Iterable<Phone> phones = phoneRepository.findAll(); phones.forEach(System.out::println); } //根据id查询 @Test public void testQuery2(){ 
    Optional<Phone> phone = phoneRepository.findById(3); phone.ifPresent(System.out::println); } //根据ids查询 @Test public void testQuery3(){ 
    Iterable<Phone> phones = phoneRepository.findAllById(Arrays.asList(1,2,3)); phones.forEach(System.out::println); } 

使用ElasticsearchRepository提供的自定义方法查询

在这里插入图片描述

 //repository自定义方法查询 @Test public void testQuery4(){ 
    List<Phone> phones = phoneRepository.findByNameLike("小米"); phones.forEach(System.out::println); } 

ElasticsearchRepository只能进行简单的查询,复杂的还要靠ElasticsearchRestTemplate

ElasticsearchRestTemplate复杂查询

讯享网 //查询name中包含“小米”的数据 @Test public void testQuery(){ 
    NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.matchQuery("name", "小米")) .build(); SearchHits<Phone> searchPhone = restTemplate.search(nativeSearchQuery, Phone.class); searchPhone.forEach(System.out::println); //SearchHit{id='2', score=1., sortValues=[], content=Phone(id=2, name=小米12pro, brand=小米), highlightFields={}} } //分页+排序 @Test public void testQuery3(){ 
    NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.matchQuery("name", "手机")) .withPageable(PageRequest.of(0, 10)) // 分页 .withSort(SortBuilders.fieldSort("id").order(SortOrder.DESC))//排序 .build(); SearchHits<Phone> search = template.search(nativeSearchQuery, Phone.class); SearchPage<Phone> page = SearchHitSupport.searchPageFor(search, nativeSearchQuery.getPageable()); System.out.println(page.getTotalElements()); System.out.println(page.getTotalPages()); System.out.println(page.getNumber()); System.out.println(page.getSize()); } 
小讯
上一篇 2025-01-04 23:08
下一篇 2025-03-23 08:18

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/36816.html