​​Spring Boot 2.x​​ 版本集成 Elasticsearch 的完整实现方案

162 阅读3分钟

以下是针对 ​​Spring Boot 2.x​​ 版本集成 Elasticsearch 的完整实现方案,重点适配 Spring Boot 2.x 与 Elasticsearch 7.x 的版本兼容性及配置差异:


一、版本兼容性说明

Spring Boot 2.x 与 Elasticsearch 的版本对应关系如下(关键版本):

Spring BootSpring Data ElasticsearchElasticsearch
2.3.x4.0.x7.6.x
2.4.x4.1.x7.9.x
2.7.x4.4.x7.17.x

​推荐组合​​:Spring Boot 2.7.x + Elasticsearch 7.17.x + Spring Data Elasticsearch 4.4.x
(若需更低版本,如 Elasticsearch 6.x,需降级 Spring Data Elasticsearch 至 3.x)


二、依赖配置(Maven)

pom.xml 中添加以下依赖(以 Spring Boot 2.7.x 为例):

<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- Spring Data Elasticsearch -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    </dependency>
    
    <!-- IK 分词器(中文分词) -->
    <dependency>
        <groupId>com.github.wensiqun</groupId>
        <artifactId>elasticsearch-analysis-ik</artifactId>
        <version>7.17.0</version>
    </dependency>
</dependencies>

三、配置文件(application.yml)

spring:
  elasticsearch:
    rest:
      uris: http://localhost:9200  # Elasticsearch 集群地址
      username: elastic            # 用户名(默认 elastic)
      password: changeme           # 密码(默认 changeme)
      connection-timeout: 5s       # 连接超时时间
      read-timeout: 30s            # 读取超时时间

四、实体类映射

1. 基础实体类(带中文分词)

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

@Data
@Document(indexName = "products", createIndex = false)  // 手动创建索引
public class Product {
    @Id
    private String id;
    
    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
    private String name;  // 中文全文检索
    
    @Field(type = FieldType.Keyword)
    private String category;  // 精确匹配
    
    @Field(type = FieldType.Double)
    private Double price;
    
    @Field(type = FieldType.Date, format = DateFormat.custom, pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
}

2. 索引创建(手动执行)

import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.stereotype.Component;

@Component
public class IndexInitializer {
    private final ElasticsearchRestTemplate elasticsearchTemplate;

    public IndexInitializer(ElasticsearchRestTemplate elasticsearchTemplate) {
        this.elasticsearchTemplate = elasticsearchTemplate;
    }

    public void createIndex() {
        if (!elasticsearchTemplate.indexExists(Product.class)) {
            elasticsearchTemplate.createIndex(Product.class);
            elasticsearchTemplate.putMapping(Product.class);
        }
    }
}

五、Repository 接口

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

public interface ProductRepository extends ElasticsearchRepository<Product, String> {
    // 按分类查询(自动生成)
    Page<Product> findByCategory(String category, Pageable pageable);
    
    // 模糊查询(名称包含关键字)
    Page<Product> findByNameContaining(String keyword, Pageable pageable);
    
    // 复杂查询(自定义方法)
    @Query("{"bool": {"must": [{"match": {"name": "?0"}}], "filter": [{"range": {"price": {"gte": ?1, "lte": ?2}}}]}}")
    Page<Product> searchWithFilters(String name, Double minPrice, Double maxPrice, Pageable pageable);
}

六、服务层实现

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.Query;
import org.springframework.stereotype.Service;

@Service
public class ProductService {
    private final ProductRepository repository;

    public ProductService(ProductRepository repository) {
        this.repository = repository;
    }

    // 分页查询所有商品
    public Page<Product> getAllProducts(int page, int size) {
        return repository.findAll(PageRequest.of(page, size));
    }

    // 高级查询(名称+价格范围)
    public Page<Product> advancedSearch(String keyword, Double minPrice, Double maxPrice, int page, int size) {
        Query query = new NativeSearchQueryBuilder()
            .withQuery(QueryBuilders.boolQuery()
                .must(QueryBuilders.matchQuery("name", keyword))
                .filter(QueryBuilders.rangeQuery("price").gte(minPrice).lte(maxPrice)))
            .withPageable(PageRequest.of(page, size))
            .build();
        return repository.search(query);
    }
}

七、控制器层

import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/products")
public class ProductController {
    private final ProductService service;

    public ProductController(ProductService service) {
        this.service = service;
    }

    // 查询所有商品(分页)
    @GetMapping
    public Page<Product> getAllProducts(
        @RequestParam(defaultValue = "0") int page,
        @RequestParam(defaultValue = "10") int size) {
        return service.getAllProducts(page, size);
    }

    // 高级搜索
    @PostMapping("/search")
    public Page<Product> searchProducts(
        @RequestBody SearchRequest request) {
        return service.advancedSearch(
            request.getKeyword(),
            request.getMinPrice(),
            request.getMaxPrice(),
            request.getPage(),
            request.getSize());
    }
}

八、版本适配注意事项

  1. ​依赖冲突​

    • Spring Boot 2.x 默认使用 Elasticsearch 7.x 客户端,若需连接 Elasticsearch 6.x,需显式指定低版本客户端:

      <dependency>
          <groupId>org.elasticsearch.client</groupId>
          <artifactId>elasticsearch-rest-high-level-client</artifactId>
          <version>7.10.0</version>
      </dependency>
      
  2. ​分词器安装​

    • 需在 Elasticsearch 中安装 IK 分词器插件:

      ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.17.0/elasticsearch-analysis-ik-7.17.0.zip
      
  3. ​日期格式​

    • Elasticsearch 7.x 默认日期格式为 strict_date_optional_time,需在实体类中显式指定格式:

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

九、常见问题解决

问题现象解决方案
NoNodeAvailableException检查 Elasticsearch 服务状态及网络连通性
中文分词失效确认 IK 分词器已正确安装,重启 Elasticsearch
字段映射不匹配删除旧索引后重建:elasticsearchTemplate.deleteIndex(Product.class)

通过以上配置,Spring Boot 2.x 可无缝对接 Elasticsearch 7.x,支持从基础查询到复杂聚合的全场景需求。实际开发中需根据业务需求调整索引分片、副本数及查询策略。