Elasticsearch介绍以及在spring项目里的使用方法

[AI生成]
Elasticsearch (简称 ES) 是目前最流行的分布式搜索引擎之一。它能快速地存储、搜索和分析海量数据。
以下我将分两部分为您介绍:首先是对 Elasticsearch 的核心概念介绍,然后是在 Spring Boot 项目中的具体整合与使用方法。

第一部分:Elasticsearch 简介

1. 什么是 Elasticsearch?

Elasticsearch 是一个基于 Apache Lucene 构建的分布式、RESTful 风格的搜索和数据分析引擎。它通常被用来替代传统数据库(如 MySQL)在模糊查询、全文检索、多维度筛选等场景下的不足。

2. 核心概念(与关系型数据库对比)

为了方便理解,我们可以将其与 MySQL 进行类比:

Elasticsearch 关系型数据库 说明
Index (索引) Database (数据库) ES 7.x 之后,Index 更像一张表,但在逻辑上相当于数据库。
Type (类型) Table (表) ES 7.x 之后已弱化,一个 Index 只对应一个 Type,通常不再提及。
Document (文档) Row (行/记录) ES 存储数据的单元,通常是 JSON 格式。
Field (字段) Column (列) 文档中的属性。
Mapping (映射) Schema (表结构) 定义字段名称、类型(text, keyword, integer等)等约束。
DSL (查询语言) SQL ES 使用 JSON 格式的 DSL 进行查询。

3. 为什么使用 ES?

  • 极致的搜索速度:基于倒排索引,毫秒级响应。
  • 模糊查询与分词:支持中文分词(如 IK 分词器),能实现“搜索‘苹果’能找到‘苹果手机’”的效果。
  • 高性能聚合分析:适合做报表、统计分析。

第二部分:在 Spring 项目中的使用方法

在 Spring Boot 项目中,主要有两种主流的使用方式:

  1. Spring Data Elasticsearch(推荐):Spring 官方封装,类似 JPA,提供 Repository 接口,开发效率高。
  2. Elasticsearch Java API Client:ES 官方提供的原生客户端,灵活性高,适合复杂查询。
    以下以 Spring Boot 2.7.x / 3.x + Spring Data Elasticsearch 为例进行演示。

1. 环境准备

确保本地或服务器已安装 Elasticsearch(建议版本 7.x 或 8.x)。

2. 引入依赖

pom.xml 中添加依赖(版本需与安装的 ES 版本对应):

<!-- Spring Boot Starter Data Elasticsearch -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<!-- Lombok (用于简化代码) -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

3. 配置连接

application.yml 中配置 ES 的地址和端口:

spring:
  elasticsearch:
    uris: http://localhost:9200  # ES 地址
    # username: elastic          # 如果开启了安全认证
    # password: your_password

4. 定义实体类

使用 @Document 注解映射索引,@Field 注解定义字段属性。

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") // 索引名称,类似于表名
public class Product {
    @Id
    private Long id; // 主键
    @Field(type = FieldType.Text, analyzer = "ik_max_word") // 文本类型,指定分词器
    private String name;
    @Field(type = FieldType.Keyword) // 关键字类型,不分词,精确匹配
    private String category;
    @Field(type = FieldType.Double)
    private Double price;
    @Field(type = FieldType.Text)
    private String description;
}

5. 定义 Repository 接口

继承 ElasticsearchRepository,即可获得基本的 CRUD 和简单查询能力。

import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface ProductRepository extends ElasticsearchRepository<Product, Long> {
    
    // 方法命名规则查询 (自动实现)
    // 查询指定分类下的商品
    List<Product> findByCategory(String category);
    
    // 价格范围查询
    List<Product> findByPriceBetween(Double min, Double max);
}

6. 业务层使用示例

基本 CRUD 操作:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class ProductService {
    @Autowired
    private ProductRepository productRepository;
    // 1. 新增/修改文档
    public void saveProduct() {
        Product product = new Product();
        product.setId(1L);
        product.setName("苹果手机 iPhone 15");
        product.setCategory("手机");
        product.setPrice(6999.00);
        productRepository.save(product); // 自动生成索引和文档
    }
    // 2. 查询单个
    public Product getProduct(Long id) {
        Optional<Product> product = productRepository.findById(id);
        return product.orElse(null);
    }
    // 3. 简单条件查询
    public List<Product> getByCategory() {
        return productRepository.findByCategory("手机");
    }
}

复杂查询:
对于复杂的业务查询(如组合条件、高亮显示、分页排序),我们需要使用 ElasticsearchRestTemplateCriteria API。

import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
import org.springframework.data.elasticsearch.core.query.Query;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class ProductSearchService {
    @Autowired
    private ElasticsearchRestTemplate elasticsearchTemplate;
    // 复杂查询示例:搜索名字包含关键词且价格在范围内的商品
    public List<Product> searchProducts(String keyword, Double minPrice, Double maxPrice) {
        // 1. 构建查询条件
        Criteria criteria = Criteria.where("name").contains(keyword)
                .and("price").between(minPrice, maxPrice);
        // 2. 构建查询对象
        Query query = new CriteriaQuery(criteria);
        // 3. 执行查询
        SearchHits<Product> searchHits = elasticsearchTemplate.search(query, Product.class);
        // 4. 转换结果
        return searchHits.stream()
                .map(SearchHit::getContent)
                .collect(Collectors.toList());
    }
}

7. 高级用法:原生 DSL 查询

如果 Spring Data 的封装无法满足需求,你可以使用 NativeQuery 直接构建 ES 的 DSL JSON 查询:

import org.springframework.data.elasticsearch.core.query.NativeQuery;
import org.elasticsearch.index.query.QueryBuilders; // 注意导入包
public List<Product> nativeSearch(String name) {
    // 使用 QueryBuilders 构建原生 Elasticsearch 查询条件
    NativeQuery query = NativeQuery.builder()
            .withQuery(QueryBuilders.matchQuery("name", name))
            .withPageable(PageRequest.of(0, 10)) // 分页
            .build();
    SearchHits<Product> hits = elasticsearchTemplate.search(query, Product.class);
    
    return hits.stream().map(SearchHit::getContent).collect(Collectors.toList());
}

总结

  1. 定位:Elasticsearch 是解决“搜索”和“模糊查询”的神器,是对传统数据库的性能补充。
  2. Spring 整合
    • 定义实体类使用 @Document 映射索引。
    • 继承 ElasticsearchRepository 实现快速 CRUD。
    • 注入 ElasticsearchRestTemplate 处理复杂查询。
  3. 注意点
    • 版本兼容性:Spring Boot 版本与 ES 版本有严格的对应关系,版本不匹配会导致连接失败。
    • 映射设计:ES 不支持多表关联,设计索引时通常采用“宽表”模式,即把需要展示的数据都冗余在一条文档中。
posted @ 2026-08-08 08:41  dirgo  阅读(9)  评论(0)    收藏  举报