Elasticsearch ElasticsearchRestTemplate 使用教程

88 阅读3分钟

Elasticsearch 7.17.15 与 ElasticsearchRestTemplate 教程

1. 版本兼容性说明

根据搜索结果,Elasticsearch 7.17.x 系列与 Spring Boot 2.7.x 版本搭配使用最为合适。因此,对于 Elasticsearch 7.17.15,推荐使用 Spring Boot 2.7.x 版本。

2. 项目配置与依赖

2.1 添加Maven依赖

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.10</version> <!-- 使用2.7.x版本 -->
</parent>

<dependencies>
    <!-- Spring Boot Elasticsearch Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    </dependency>
    
    <!-- 可以显式指定客户端版本以匹配Elasticsearch 7.17.15 -->
    <dependency>
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>elasticsearch-rest-high-level-client</artifactId>
        <version>7.17.15</version>
    </dependency>
    
    <dependency>
        <groupId>org.elasticsearch</groupId>
        <artifactId>elasticsearch</artifactId>
        <version>7.17.15</version>
    </dependency>
</dependencies>

2.2 配置application.yml

spring:
  elasticsearch:
    rest:
      uris: http://localhost:9200
      # 如果Elasticsearch设置了安全认证
      # username: elastic
      # password: changeme

3. ElasticsearchRestTemplate 配置类

对于Elasticsearch 7.17.15,我们需要确保正确配置RestHighLevelClient:

import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.RestClients;
import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;

@Configuration
public class ElasticsearchConfig extends AbstractElasticsearchConfiguration {

    @Override
    @Bean
    public RestHighLevelClient elasticsearchClient() {
        ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                .connectedTo("localhost:9200")
                // 如果需要SSL配置
                // .usingSsl()
                // 如果需要认证
                // .withBasicAuth("elastic", "changeme")
                .build();
        
        return RestClients.create(clientConfiguration).rest();
    }

    @Bean
    public ElasticsearchRestTemplate elasticsearchRestTemplate() {
        return new ElasticsearchRestTemplate(elasticsearchClient());
    }
}

4. 创建实体类

import lombok.Data;
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;

@Data
@Document(indexName = "product_index", shards = 1, replicas = 0)
public class Product {
    @Id
    private String id;
    
    @Field(type = FieldType.Text, analyzer = "ik_max_word") // 使用IK分词器
    private String name;
    
    @Field(type = FieldType.Double)
    private Double price;
    
    @Field(type = FieldType.Keyword)
    private String category;
    
    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String description;
    
    @Field(type = FieldType.Date, format = {}) // 7.17版本的日期格式配置
    private String createTime;
}

5. 基本操作示例

5.1 索引操作

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.stereotype.Service;

@Service
public class ElasticsearchService {
    
    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;
    
    // 创建索引
    public boolean createIndex() {
        return elasticsearchRestTemplate.indexOps(Product.class).create();
    }
    
    // 检查索引是否存在
    public boolean indexExists() {
        return elasticsearchRestTemplate.indexOps(Product.class).exists();
    }
    
    // 删除索引
    public boolean deleteIndex() {
        return elasticsearchRestTemplate.indexOps(Product.class).delete();
    }
}

5.2 文档操作

// 添加文档
public Product saveProduct(Product product) {
    return elasticsearchRestTemplate.save(product);
}

// 根据ID查询
public Product getProductById(String id) {
    return elasticsearchRestTemplate.get(id, Product.class);
}

// 更新文档
public Product updateProduct(Product product) {
    return elasticsearchRestTemplate.save(product);
}

// 删除文档
public void deleteProductById(String id) {
    elasticsearchRestTemplate.delete(id, Product.class);
}

5.3 查询操作

import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import java.util.List;
import java.util.stream.Collectors;

// 全文搜索
public List<Product> searchProducts(String keyword) {
    NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
            .withQuery(QueryBuilders.multiMatchQuery(keyword, "name", "description"))
            .build();
    
    SearchHits<Product> searchHits = elasticsearchRestTemplate.search(searchQuery, Product.class);
    
    return searchHits.stream()
            .map(SearchHit::getContent)
            .collect(Collectors.toList());
}

// 条件查询 - 价格范围
public List<Product> searchByPriceRange(double minPrice, double maxPrice) {
    NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
            .withQuery(QueryBuilders.rangeQuery("price")
                    .from(minPrice)
                    .to(maxPrice))
            .build();
    
    SearchHits<Product> searchHits = elasticsearchRestTemplate.search(searchQuery, Product.class);
    
    return searchHits.stream()
            .map(SearchHit::getContent)
            .collect(Collectors.toList());
}

// 分页查询
public List<Product> searchProductsWithPage(String keyword, int page, int size) {
    NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
            .withQuery(QueryBuilders.matchQuery("name", keyword))
            .withPageable(PageRequest.of(page, size))
            .build();
    
    SearchHits<Product> searchHits = elasticsearchRestTemplate.search(searchQuery, Product.class);
    
    return searchHits.stream()
            .map(SearchHit::getContent)
            .collect(Collectors.toList());
}

6. 7.17.15 版本特有注意事项

  1. 版本匹配:确保Spring Boot 2.7.x与Elasticsearch 7.17.15版本严格匹配,避免兼容性问题

  2. 安全配置:如果使用Elasticsearch 7.17的安全功能(默认启用),需要在配置中提供正确的用户名和密码

  3. 索引API变化:7.x版本中索引操作与6.x版本有所不同,移除了类型(type)概念

  4. 查询DSL差异:Elasticsearch 7.x在查询语法上有一些变化,特别是在聚合查询和排序方面

7. 完整示例 - 控制器

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;

@RestController
@RequestMapping("/api/products")
public class ProductController {
    
    @Autowired
    private ElasticsearchService elasticsearchService;
    
    // 创建索引
    @PostMapping("/index/create")
    public boolean createIndex() {
        return elasticsearchService.createIndex();
    }
    
    // 添加产品
    @PostMapping
    public Product addProduct(@RequestBody Product product) {
        return elasticsearchService.saveProduct(product);
    }
    
    // 根据ID获取产品
    @GetMapping("/{id}")
    public Product getProduct(@PathVariable String id) {
        return elasticsearchService.getProductById(id);
    }
    
    // 搜索产品
    @GetMapping("/search")
    public List<Product> searchProducts(@RequestParam String keyword) {
        return elasticsearchService.searchProducts(keyword);
    }
    
    // 价格范围搜索
    @GetMapping("/search/price")
    public List<Product> searchByPrice(@RequestParam double min, @RequestParam double max) {
        return elasticsearchService.searchByPriceRange(min, max);
    }
    
    // 删除产品
    @DeleteMapping("/{id}")
    public void deleteProduct(@PathVariable String id) {
        elasticsearchService.deleteProductById(id);
    }
}

8. 常见问题解决

  1. 连接问题:检查Elasticsearch服务是否启动,端口是否正确(默认9200)

  2. 版本冲突:如果出现依赖冲突,可使用Maven Dependency Plugin分析并排除冲突依赖

  3. 权限问题:7.17版本默认启用安全功能,确保配置了正确的用户名密码

  4. 索引创建失败:检查实体类的注解配置是否正确,特别是字段映射类型

通过以上配置和示例,你可以成功在Spring Boot项目中集成Elasticsearch 7.17.15并使用ElasticsearchRestTemplate进行各种操作。根据实际项目需求,你可以进一步扩展和优化这些功能。