Elasticsearch 超全入门实战教程

Elasticsearch 超全入门实战教程

博客前言

Elasticsearch(简称ES)是一款基于Lucene实现的分布式、高扩展、实时全文搜索引擎与数据分析引擎,广泛应用于站内搜索、日志分析、大数据检索、商品搜索、智能推荐等场景。

相比于MySQL模糊查询(like %xxx%),ES基于倒排索引实现分词检索,支持海量数据毫秒级查询、模糊匹配、高亮显示、分组聚合统计,是后端开发必备核心技能。

本文从零梳理ES核心原理、基础运维、全套可复制DSL练习Demo、避坑指南,最后提供SpringBoot 整合ES完整CRUD企业级代码,零基础可直接上手实战、用于项目开发与学习面试。

一、Elasticsearch 核心基础概念(必懂)

为方便理解,将ES核心概念与MySQL做精准类比,快速建立认知:

ES核心名词 MySQL对应概念 详细说明
Index(索引) Database(数据库) 数据存储容器,同一类业务数据统一存放,支持分片、副本扩容
Mapping(映射) Table(数据表结构) 定义索引内字段名称、数据类型、分词规则、索引规则,约束数据格式
Document(文档) Row(数据行) ES最小数据单元,JSON格式存储,每条文档拥有唯一_id
Field(字段) Column(字段列) 文档中的单个属性,比如商品标题、价格、分类
Shard(分片) 无对应概念 数据拆分存储,解决单节点数据上限,支持分布式扩容
Replica(副本) 无对应概念 分片备份,保障集群高可用,节点宕机不丢失数据

1.1 核心字段类型(高频必考)

ES字段类型决定查询方式,90%新手报错都源于类型使用错误:

  • text:分词字段,支持全文模糊检索,不支持精确匹配、排序、聚合。适用于文章内容、商品标题、简介等长文本。

  • keyword:不分词,完整精确匹配,支持排序、分组聚合、去重。适用于分类、标签、状态、手机号、账号等固定文本。

  • 数值类型:long、integer、double、float,用于价格、数量、ID,支持范围查询、数值聚合。

  • date:日期类型,支持标准日期格式,可按时间范围检索、时间分组统计。

  • boolean:布尔类型,true/false,用于状态开关。

1.2 核心特性

  • 默认端口:服务端口9200(HTTP)、集群通信端口9300(TCP)

  • 通信方式:RESTful JSON API,所有操作均通过JSON请求实现

  • 数据结构:天然JSON结构化存储,无需提前建表(推荐手动建Mapping)

  • 检索核心:倒排索引,通过关键词匹配文档,而非逐行扫描

二、ES集群运维基础DSL(生产常用)

所有语句可直接在Kibana-Dev Tools、Postman、Apifox中执行,开箱即用。

2.1 集群状态查询

Plain 复制代码
# 查看集群整体健康状态(核心)
GET /_cluster/health

# 查看所有索引列表(带详细信息)
GET /_cat/indices?v

# 查看集群节点信息
GET /_cat/nodes?v

# 查看集群分片分配情况
GET /_cat/shards?v

集群状态说明:

  • green:主分片、副本分片全部正常,集群完全健康

  • yellow:主分片正常,副本分片未分配(单节点集群默认状态,不影响使用)

  • red:主分片丢失,对应索引数据不可用,业务报错

三、索引 Index 全套操作 DSL 练习Demo

3.1 创建索引(手动指定Mapping,生产规范用法)

生产环境禁止动态自动创建索引,必须手动定义字段类型,避免类型混乱导致查询异常。

Plain 复制代码
# 创建商品索引 products
PUT /products
{
  "settings": {
    "number_of_shards": 1,    # 主分片数,单机测试设1
    "number_of_replicas": 0   # 副本数,单机设0,避免yellow状态
  },
  "mappings": {
    "properties": {
      "title": {"type": "text", "analyzer": "ik_max_word"},  # 商品标题,中文分词
      "desc": {"type": "text", "analyzer": "ik_max_word"},   # 商品描述
      "category": {"type": "keyword"},                       # 商品分类(精确匹配)
      "price": {"type": "double"},                           # 商品价格
      "stock": {"type": "integer"},                          # 库存数量
      "isSale": {"type": "boolean"},                         # 是否在售
      "createTime": {"type": "date", "format": "yyyy-MM-dd HH:mm:ss"} # 创建时间
    }
  }
}

3.2 索引查询、删除、更新

Plain 复制代码
# 查询索引结构Mapping
GET /products/_mapping

# 查询索引配置信息
GET /products/_settings

# 删除索引(高危操作,生产谨慎!)
DELETE /products

四、文档 Document CRUD 全套练习Demo

针对products索引,完成增删改查全套实操语句,覆盖日常开发所有场景。

4.1 新增文档

Plain 复制代码
# 1. 指定ID新增文档
PUT /products/_doc/1
{
  "title": "机械游戏键盘",
  "desc": "青轴机械键盘,电竞专用,手感清脆",
  "category": "数码外设",
  "price": 599.9,
  "stock": 120,
  "isSale": true,
  "createTime": "2026-08-28 10:00:00"
}

# 2. 自动生成ID新增文档(POST方式)
POST /products/_doc
{
  "title": "无线静音鼠标",
  "desc": "办公静音无线鼠标,长续航",
  "category": "数码外设",
  "price": 199.9,
  "stock": 200,
  "isSale": true,
  "createTime": "2026-08-28 10:10:00"
}

4.2 查询文档

Plain 复制代码
# 根据ID单条查询
GET /products/_doc/1

# 查询所有文档(size指定返回条数)
GET /products/_search
{
  "query": {
    "match_all": {}
  },
  "size": 100
}

4.3 更新文档(两种方式,重点区分)

Plain 复制代码
# 1. 全量更新(覆盖所有字段,缺失字段会丢失)
PUT /products/_doc/1
{
  "title": "机械游戏键盘",
  "desc": "青轴机械键盘,电竞专用,手感清脆",
  "category": "数码外设",
  "price": 559.9,
  "stock": 100,
  "isSale": true,
  "createTime": "2026-08-28 10:00:00"
}

# 2. 局部更新(推荐!只修改指定字段,不影响其他数据)
POST /products/_update/1
{
  "doc": {
    "price": 529.9,
    "stock": 95
  }
}

4.4 删除文档

Plain 复制代码
# 根据ID删除单条文档
DELETE /products/_doc/1

4.5 批量导入数据 _bulk(高效批量操作)

批量新增/更新/删除数据,适合初始化数据、批量同步业务数据,效率远高于单条操作。

Plain 复制代码
POST /products/_bulk
{"index":{"_id":2}}
{"title":"降噪蓝牙耳机","desc":"无线降噪入耳式耳机","category":"数码影音","price":299.9,"stock":300,"isSale":true,"createTime":"2026-08-28 10:20:00"}
{"index":{"_id":3}}
{"title":"纯棉休闲T恤","desc":"夏季宽松百搭纯棉T恤","category":"服饰穿搭","price":79.9,"stock":500,"isSale":true,"createTime":"2026-08-28 10:30:00"}
{"index":{"_id":4}}
{"title":"电竞游戏耳机","desc":"头戴式降噪电竞耳机","category":"数码外设","price":399.9,"stock":180,"isSale":false,"createTime":"2026-08-28 10:40:00"}

五、核心 Query DSL 高级查询(开发高频)

DSL查询是ES核心,所有复杂检索、过滤、分页、排序、高亮均基于此实现。

5.1 全文分词查询 match(text字段专用)

自动分词匹配,模糊检索,适合搜索商品标题、文章内容。

Plain 复制代码
# 搜索标题包含「键盘」的商品
GET /products/_search
{
  "query": {
    "match": {
      "title": "键盘"
    }
  }
}

5.2 精确查询 term(keyword字段专用)

不分词,完全精确匹配,用于分类、标签、状态筛选。

Plain 复制代码
# 精确查询分类为「数码外设」的商品
GET /products/_search
{
  "query": {
    "term": {
      "category": "数码外设"
    }
  }
}

5.3 范围查询 range(数值/时间)

Plain 复制代码
# 查询价格100~600元的在售商品
GET /products/_search
{
  "query": {
    "range": {
      "price": {
        "gte": 100,
        "lte": 600
      }
    }
  }
}

操作符说明:gte≥、lte≤、gt>、lt<

5.4 多条件组合查询 bool(最常用)

  • must:必须匹配,参与相关性得分计算

  • filter:必须匹配,不计算得分、性能更高,纯过滤优先用filter

  • should:或条件,满足其一即可

  • must_not:必须不匹配,排除条件

Plain 复制代码
# 标题含「数码」、价格200以上、在售商品
GET /products/_search
{
  "query": {
    "bool": {
      "must": [
        {"match": {"title": "数码"}}
      ],
      "filter": [
        {"range": {"price": {"gte": 200}}},
        {"term": {"isSale": true}}
      ]
    }
  }
}

5.5 分页、排序、高亮查询

Plain 复制代码
# 分页+排序+关键词高亮
GET /products/_search
{
  "query": {
    "match": {
      "title": "耳机"
    }
  },
  "from": 0,
  "size": 5,
  "sort": [
    {"price": {"order": "desc"}}
  ],
  "highlight": {
    "fields": ["title"],
    "pre_tags": "<span style='color:red'>",
    "post_tags": "</span>"
  }
}

5.6 聚合查询(分组统计,类似MySQL group by)

Plain 复制代码
# 按商品分类分组,统计每组数量、平均价格
GET /products/_search
{
  "size": 0,
  "aggs": {
    "group_by_category": {
      "terms": {"field": "category"}
    },
    "avg_price": {
      "avg": {"field": "price"}
    }
  }
}

六、ES 高频避坑总结(新手必看)

  1. 字段类型不匹配:text字段不能用term精确查询,keyword字段不支持分词模糊搜索

  2. 查询性能问题:纯过滤条件务必放filter,不要放must,大幅提升查询效率

  3. 文档更新原理:ES更新是「删除旧文档+新建文档」,禁止高频单条更新,批量更新用_bulk

  4. 禁止动态Mapping:自动创建索引会导致字段类型错乱,引发查询、聚合报错

  5. 分页深度限制:from+size分页不支持超大深度分页,深分页用scroll或search_after

七、SpringBoot 整合 Elasticsearch 完整 CRUD 实战

基于 Spring Data Elasticsearch 实现,代码简洁、适配企业级开发,包含:依赖配置、实体映射、Repository、Service、Controller、完整测试。

7.1 环境版本适配

  • SpringBoot:2.7.x / 3.2.x

  • Elasticsearch:7.x / 8.x(本文兼容主流版本)

  • JDK:1.8+

7.2 Maven 核心依赖

Plain 复制代码
<!-- SpringBoot ES 启动器 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

<!-- 简化代码 -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

7.3 application.yml 配置文件

Plain 复制代码
spring:
  elasticsearch:
    uris: http://127.0.0.1:9200  # ES服务地址
# 8.x版本如需账号密码认证,追加配置
#    username: elastic
#    password: 123456

7.4 ES实体类(映射索引结构)

精准对应前文products索引Mapping,绑定字段类型与分词规则

Plain 复制代码
package com.es.demo.entity;

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;

import java.util.Date;

@Data
// 绑定索引名、分片、副本
@Document(indexName = "products", shards = 1, replicas = 0)
public class ProductDoc {

    // 文档唯一ID
    @Id
    private String id;

    // 商品标题:分词字段
    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String title;

    // 商品描述:分词字段
    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String desc;

    // 商品分类:精确字段
    @Field(type = FieldType.Keyword)
    private String category;

    // 价格
    @Field(type = FieldType.Double)
    private Double price;

    // 库存
    @Field(type = FieldType.Integer)
    private Integer stock;

    // 是否在售
    @Field(type = FieldType.Boolean)
    private Boolean isSale;

    // 创建时间
    @Field(type = FieldType.Date)
    private Date createTime;
}

7.5 Repository 持久层(ES数据操作层)

继承ElasticsearchRepository,自带基础CRUD,支持自定义DSL查询

Plain 复制代码
package com.es.demo.repository;

import com.es.demo.entity.ProductDoc;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface ProductRepository extends ElasticsearchRepository<ProductDoc, String> {

    // 自定义方法:根据标题模糊分词查询
    List<ProductDoc> findByTitle(String title);

    // 根据分类精确查询
    List<ProductDoc> findByCategory(String category);
}

7.6 Service 业务层(完整CRUD逻辑)

Plain 复制代码
package com.es.demo.service;

import com.es.demo.entity.ProductDoc;
import com.es.demo.repository.ProductRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
@RequiredArgsConstructor
public class ProductService {

    private final ProductRepository productRepository;
    private final ElasticsearchOperations elasticsearchOperations;

    // 新增/更新文档(ID存在则更新,不存在则新增)
    public void saveProduct(ProductDoc productDoc) {
        productRepository.save(productDoc);
    }

    // 根据ID查询
    public Optional<ProductDoc> getById(String id) {
        return productRepository.findById(id);
    }

    // 根据ID删除
    public void deleteById(String id) {
        productRepository.deleteById(id);
    }

    // 分页查询所有
    public Page<ProductDoc> pageList(int pageNum, int pageSize) {
        PageRequest pageRequest = PageRequest.of(pageNum - 1, pageSize);
        return productRepository.findAll(pageRequest);
    }

    // 标题模糊搜索
    public List<ProductDoc> searchByTitle(String title) {
        return productRepository.findByTitle(title);
    }

    // 分类精确查询
    public List<ProductDoc> searchByCategory(String category) {
        return productRepository.findByCategory(category);
    }
}

7.7 Controller 控制层(接口暴露)

Plain 复制代码
package com.es.demo.controller;

import com.es.demo.entity.ProductDoc;
import com.es.demo.service.ProductService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

@RestController
@RequestMapping("/es/product")
@RequiredArgsConstructor
public class ProductController {

    private final ProductService productService;

    // 新增/更新商品
    @PostMapping("/save")
    public String save(@RequestBody ProductDoc productDoc) {
        productService.saveProduct(productDoc);
        return "操作成功";
    }

    // 根据ID查询
    @GetMapping("/{id}")
    public Optional<ProductDoc> getById(@PathVariable String id) {
        return productService.getById(id);
    }

    // 根据ID删除
    @DeleteMapping("/{id}")
    public String delete(@PathVariable String id) {
        productService.deleteById(id);
        return "删除成功";
    }

    // 分页查询
    @GetMapping("/page")
    public Page<ProductDoc> page(@RequestParam int pageNum, @RequestParam int pageSize) {
        return productService.pageList(pageNum, pageSize);
    }

    // 标题搜索
    @GetMapping("/search/title")
    public List<ProductDoc> searchTitle(@RequestParam String title) {
        return productService.searchByTitle(title);
    }

    // 分类查询
    @GetMapping("/search/category")
    public List<ProductDoc> searchCategory(@RequestParam String category) {
        return productService.searchByCategory(category);
    }
}

7.8 高级自定义DSL查询(复杂业务)

适用于多条件组合、范围、排序、高亮等复杂场景,在Service中新增自定义查询方法:

Plain 复制代码
// 复杂多条件组合查询
public Page<ProductDoc> complexSearch(String keyword, Double minPrice, int pageNum, int pageSize) {
    NativeSearchQuery query = new NativeSearchQueryBuilder()
            .withQuery(QueryBuilders.matchQuery("title", keyword))
            .withFilter(QueryBuilders.rangeQuery("price").gte(minPrice))
            .withPageable(PageRequest.of(pageNum - 1, pageSize))
            .withSort(SortBuilders.fieldSort("price").order(SortOrder.DESC))
            .build();
    return elasticsearchOperations.search(query, ProductDoc.class).getPageable();
}

八、全文总结

  1. ES核心优势:基于倒排索引实现高效全文检索,适配海量数据搜索场景,弥补MySQL模糊查询性能短板;

  2. 实操核心:区分text/keyword字段类型、熟练掌握bool组合查询、聚合统计、批量操作;

  3. 开发落地:Spring Data ES 简化开发,基础CRUD开箱即用,复杂业务通过原生DSL实现,完全适配企业级搜索需求。

本文所有DSL语句、Java代码均可直接复制运行,可作为学习笔记、项目模板、面试复习资料。

相关推荐
数据皮皮侠22 分钟前
企业知识重组能力数据(1988-2025)
大数据·人工智能·搜索引擎·智慧城市·制造
attitude.x2 小时前
液冷超充桩厂家哪家好?2026年功率与散热对比
大数据
2601_960620378 小时前
计算机、大数据专业大学考什么证?适配校招实用证书清单
大数据
智恒百亿8 小时前
RTX 5090 全场景技术应用解析:从游戏算力到专业生产力落地
大数据·服务器·游戏
智圣新创019 小时前
面向多级组织协同场景 高校第二课堂一站式管理中枢落地全场景实操答疑
大数据·人工智能
商业咨询信息9 小时前
中之网科技江苏有限公司:长三角制造企业短视频代运营服务深度测评
搜索引擎
黎阳之光9 小时前
打破堆场感知黑盒:黎阳之光视频孪生,构建港口码头网格化透明管控新体系
大数据·人工智能·算法·安全·数字孪生
大模型码小白10 小时前
AI 对话流性能调优:万级消息的虚拟滚动落地
java·大数据·前端·javascript·人工智能·算法·机器学习
数智启示录10 小时前
Flink CDC 机制精讲(二):Checkpoint Barrier 如何形成一致快照 【面试宝典】
大数据·经验分享·面试·flink