Springboot 使用ElasticSearch6.x

原创
2020/05/18 01:32
阅读数 261

SpringBoot集成ElasticSearch很简单,只需要引入spring-data-elasticsearch依赖,添加配置即可。由于Elasticsearch版本较多目前已经7.5.x,spring-data-elasticsearch与对应的版本兼容性如下图:

 

 

一、项目结构

 

二、添加依赖,修改pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.piao</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>es-demo</name>
    <description>ElasticSearch Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath/>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--elasticsearch-->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-elasticsearch</artifactId>
            <version>3.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>provided</scope>
        </dependency>
        <!--<dependency>-->
            <!--<groupId>junit</groupId>-->
            <!--<artifactId>junit</artifactId>-->
            <!--<scope>test</scope>-->
        <!--</dependency>-->

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

 

三、配置信息,修改application.yml

elasticsearch:
    host: 127.0.0.1
    port: 9300
    clustername: piao
    search:
        pool:
            size: 5

 

四、编写代码

4.1、编写ElasticsearchConfig

package com.piao.config;

import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;

import java.net.InetAddress;

@Slf4j
@Configuration
@EnableElasticsearchRepositories(basePackages = "com.piao.dao")
public class ElasticsearchConfig {

    @Value("${elasticsearch.host}")
    private String host;

    @Value("${elasticsearch.port}")
    private int port;

    @Value("${elasticsearch.clustername}")
    private String clusterName;

    @Value("${elasticsearch.search.pool.size}")
    private Integer threadPoolSearchSize;

    @Bean
    public Client client() throws Exception {
        Settings esSettings = Settings.builder()
                .put("cluster.name", clusterName)
                //增加嗅探机制,找到ES集群,非集群置为false
                .put("client.transport.sniff", true)
                //增加线程池个数
                .put("thread_pool.search.size", threadPoolSearchSize)
                .build();
        return new PreBuiltTransportClient(esSettings)
                //如果不需要设置ES集群可以不用配置一个主机和端口。我这里配置了ES集群的主机和端口
                .addTransportAddress(new TransportAddress(InetAddress.getByName(host), port));
    }

    @Bean
    public ElasticsearchTemplate elasticsearchTemplate() throws Exception {
        try {
            return new ElasticsearchTemplate(client());
        } catch (Exception e) {
            log.error("初始化ElasticsearchTemplate失败");
            return new ElasticsearchTemplate(client());
        }
    }
}

 

4.2、编写CostumeRepository

package com.piao.dao;

import com.piao.entity.Costume;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface CostumeRepository extends ElasticsearchRepository<Costume, String> {

}

 

4.3、编写DO对象 Costume

package com.piao.entity;

import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

import java.math.BigDecimal;
import java.util.Date;

@Data
@Document(indexName = "goods", type = "costume", useServerConfiguration = true, createIndex = false)
public class Costume {

    @Id
    private String id;

    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
    private String name;

    @Field(type = FieldType.Integer)
    private Integer num;

    @Field(type = FieldType.Double)
    private BigDecimal price;

    @Field(type = FieldType.Integer)
    private Integer type;

    @Field(type = FieldType.Date, pattern = "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis", format = DateFormat.custom)
    private Date date;

    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
    private String describe;


}

关于上面类中使用的相关spring-data-elasticsearch注解的解释:

@Document 代表在定义ES中的文档document

  • indexName 索引名称,一般为全小写字母,可以看成是数据库名称
  • type 类型,可以看成是数据库表名
  • useServerConfiguration 是否使用系统配置
  • shards 集群模式下分片存储,默认分5片
  • replicas 数据复制几份,默认1份
  • refreshInterval 多久刷新数据,默认1s
  • indexStoreType 索引存储模式,默认FS
  • createIndex 是否创建索引,默认True,代表不存在indexName对应索引时,自动创建

@Field 文档中的字段类型,对应的是ES中document的Mappings概念,是在设置字段类型

  • type 字段类型,默认按照java类型进行推断,也可以手动指定,通过FieldType枚举

  • index 是否为每个字段创建倒排索引,默认true,如果不想通过某个field的关键字来查询到文档,设置为false即可

  • pattern 用在日期上类型字段上 format = DateFormat.custom, pattern = “yyyy-MM-dd HH:mm:ss:SSS”

  • searchAnalyzer 指定搜索的分词,ik分词只有ik_smart(粗粒度)和ik_max_word(细粒度)两个模式,具体差异大家可以去ik官网查看

  • analyzer 指定索引时的分词器,ik分词器有ik_smart和ik_max_word

  • store 是否存储到文档的_sourch字段中,默认false情况下不存储

 

五、验证结果

5.1、编写单元测试类 CostumeTest

package com.piao;

import com.piao.dao.CostumeRepository;
import com.piao.entity.Costume;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.MatchPhraseQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.test.context.junit4.SpringRunner;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Iterator;
import java.util.Optional;
import java.util.UUID;

@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class CostumeTest {

    @Autowired
    CostumeRepository goodsRepository;

    @Test
    public void saveCostume(){
        Costume costume = new Costume();
        costume.setId(UUID.randomUUID().toString());
        costume.setDate(new Date());
        costume.setName("太平鸟燕尾服");
        costume.setDescribe("限时优惠太平鸟燕尾服,8折出售");
        goodsRepository.save(costume);

        System.out.println(costume.getId());
    }

    @Test
    public void updateCostume(){
        String id = "d1e18d38-1763-4aa8-a274-e0a6737f7519";
        Optional<Costume> itemOptional = goodsRepository.findById(id);
        Costume costume = itemOptional.get();
        costume.setNum(20);
        costume.setPrice(new BigDecimal("680.50"));
        goodsRepository.save(costume);
    }

    @Test
    public void deleteCostume(){
        Costume costume = new Costume();
        costume.setId("bd057656-e0f8-4b49-9ed8-045712d06c83");

        goodsRepository.delete(costume);
    }

    /**
     * 根据Id查询
     */
    @Test
    public void findGoodsById() {
        Optional<Costume> goods = goodsRepository.findById("2");
        System.out.println(goods.get());
    }

    /**
     * 分词查询
     */
    @Test
    public void findCostumeByName() {
        String keyWord = "运动鞋";
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("name", keyWord);
        Iterable<Costume> search = goodsRepository.search(matchQueryBuilder);

        Iterator<Costume> iterator = search.iterator();
        while (iterator.hasNext()) {
            Costume next = iterator.next();
            System.out.println(next);
        }
    }

    /**
     * 全匹配查询
     */
    @Test
    public void findCostumeByNam2() {
        String keyWord = "太平鸟";
        MatchPhraseQueryBuilder matchPhraseQueryBuilder = QueryBuilders.matchPhraseQuery("name", keyWord);
        Iterable<Costume> search = goodsRepository.search(matchPhraseQueryBuilder);

        Iterator<Costume> iterator = search.iterator();
        while (iterator.hasNext()) {
            Costume next = iterator.next();
            System.out.println(next);
        }
    }

    /**
     * 分页查询
     */
    @Test
    public void findCostumeByNamPage() {
        Sort date = Sort.by("date").ascending();
        Pageable pageable = PageRequest.of(0, 5, date);

        String keyWord = "太平鸟运动鞋";
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("name", keyWord);
        Iterable<Costume> search = goodsRepository.search(matchQueryBuilder, pageable);

        Iterator<Costume> iterator = search.iterator();
        while (iterator.hasNext()) {
            Costume next = iterator.next();
            System.out.println(next);
        }
    }

}

 

更多阅读

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部