ElasticSearch 从入门到实战

一、ElasticSearch 核心介绍

1.1 为什么选择 ElasticSearch?

在电商、资讯等平台的搜索场景中,用户输入的关键词往往是随意且多样化的,传统数据库的字段匹配查询无法满足 "千奇百怪" 的检索需求。而 ElasticSearch(ES)作为基于 Lucene 的分布式全文检索服务器,采用词元匹配方案(例如 "北京天安门" 会被切分为 "北京""天安门" 等词元),能精准匹配用户的模糊搜索需求。

1.2 ES 核心特性

  • 基于 Lucene 封装,隐藏底层复杂性,对外提供 RESTful API 操作索引 / 搜索;
  • 分布式架构,支持水平扩展,满足高并发、大数据量场景;
  • 实时搜索,毫秒级响应,适用于云计算、企业级搜索引擎;
  • 开源免费(Apache 许可),生态完善,Github、电商平台等大规模应用。

1.3 ES vs Solr

  • 现有 Solr 集群能满足需求则无需替换;
  • 新项目优先选 ES,大规模搜索场景(如 Github)验证了其稳定性和性能。

1.4 核心原理:倒排索引

倒排索引是 ES 实现全文检索的核心,核心逻辑是从关键字到文档的映射(已知关键字找文档),由三部分组成:

  1. 原始数据以Document形式存储;
  2. 文档内容分词,生成不重复的 "分词列表";
  3. 每个分词与对应的 Document 建立关联。

例如搜索 "quick brown" 时,ES 会匹配包含该分词的文档,并根据匹配度排序,优先返回相关性更高的结果。

二、环境搭建(CentOS)

2.1 环境前置要求

  1. JDK 版本≥1.8.0_131;
  2. 至少 4096 线程池、262144 字节以上虚拟内存,建议虚拟机内存≥1.5G;
  3. ES 5.0 + 禁止 root 账号启动,需创建普通用户;
  4. 插件要求 CentOS 内核≥3.5(CentOS 6 需特殊配置)。

2.2 ElasticSearch 安装步骤

2.2.1 创建专用用户
复制代码
# 创建elk用户组
groupadd elk
# 创建admin用户并设置密码
useradd admin
passwd admin
# 将admin加入elk组
usermod -G elk admin
# 分配目录权限(ES安装目录)
chown -R admin:elk /usr/upload
chown -R admin:elk /usr/local
# 切换到admin用户
su admin
2.2.2 解压安装
复制代码
# 下载ES 6.2.3(可替换为对应版本)
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.2.3.tar.gz
# 解压到指定目录
tar -zxvf elasticsearch-6.2.3.tar.gz -C /usr/local
2.2.3 目录结构说明
目录 作用
bin 可执行文件(启动 / 停止 ES)
config 配置文件(elasticsearch.yml、jvm.options、log4j2.properties)
lib 依赖 jar 包
logs 日志文件
modules 核心功能模块(aggs、reindex 等)
plugins 插件目录(IK 分词器等)
data 索引数据存储目录(启动后自动创建)
2.2.4 核心配置修改
1. elasticsearch.yml(核心配置)
复制代码
# 集群名称
cluster.name: power_shop
# 节点名称
node.name: power_shop_node_1
# 绑定所有IP,允许外网访问
network.host: 0.0.0.0
# HTTP端口
http.port: 9200
# 集群通信端口
transport.tcp.port: 9300
# 集群节点列表
discovery.zen.ping.unicast.hosts: ["192.168.61.135:9300", "192.168.61.136:9300"]
# 数据存储路径
path.data: /usr/local/elasticsearch-6.2.3/data
# 日志存储路径
path.logs: /usr/local/elasticsearch-6.2.3/logs
# 允许跨域(对接head插件)
http.cors.enabled: true
http.cors.allow-origin: /.*/
# 禁用内核检查(CentOS 6兼容)
bootstrap.system_call_filter: false
2. jvm.options(JVM 内存配置)
复制代码
# 最小/最大堆内存,建议设为相等且不超过物理内存的1/2
-Xms512m
-Xmx512m
2.2.5 系统参数调优(解决启动报错)
1. 文件描述符限制
复制代码
# 切换到root用户
su root
# 编辑配置文件
vim /etc/security/limits.conf
# 追加内容
* soft nofile 65536
* hard nofile 65536
2. 线程数限制
复制代码
vim /etc/security/limits.d/90-nproc.conf
# 修改内容
* soft nproc 4096
3. 虚拟内存限制
复制代码
vim /etc/sysctl.conf
# 追加内容
vm.max_map_count=655360
# 使配置生效
sysctl -p
2.2.6 启动与测试
复制代码
# 启动ES(后台运行)
/usr/local/elasticsearch-6.2.3/bin/elasticsearch -d
# 查看进程
ps -ef | grep elasticsearch
# 测试是否启动成功(浏览器访问)
http://192.168.204.132:9200

成功返回示例:

复制代码
{
  "name" : "power_shop_node_1",
  "cluster_name" : "power_shop",
  "version" : {
    "number" : "6.2.3",
    "lucene_version" : "7.2.1"
  },
  "tagline" : "You Know, for Search"
}

2.3 Kibana 安装(可视化管理)

2.3.1 下载与解压(Windows/Linux 均可)
复制代码
# Linux下载示例
wget https://artifacts.elastic.co/downloads/kibana/kibana-6.2.3-linux-x86_64.tar.gz
tar -zxvf kibana-6.2.3-linux-x86_64.tar.gz -C /usr/local
2.3.2 配置修改(config/kibana.yml)
复制代码
# 端口
server.port: 5601
# 允许远程访问
server.host: "0.0.0.0"
# 关联ES地址
elasticsearch.url: http://192.168.204.132:9200
2.3.3 启动与测试
复制代码
# 启动Kibana
/usr/local/kibana-6.2.3/bin/kibana
# 浏览器访问
http://127.0.0.1:5601

2.4 Head 插件安装(ES 可视化)

Head 是 ES 的可视化管理插件,需依赖 Node.js:

复制代码
# 下载源码
git clone https://github.com/mobz/elasticsearch-head.git
# 进入目录
cd elasticsearch-head
# 安装依赖
npm install
# 启动
npm run start
# 浏览器访问
http://127.0.0.1:9100/

三、ES 快速入门(Kibana 实操)

3.1 索引(Index)管理

3.1.1 创建索引
复制代码
# PUT /索引名
PUT /java06
{
  "settings": {
    "number_of_shards": 2,  # 主分片数(一旦创建不可修改)
    "number_of_replicas": 1 # 副本数(可修改,单机建议设0)
  }
}
3.1.2 修改索引(仅副本数)
复制代码
PUT /java06/_settings
{
  "number_of_replicas" : 1
}
3.1.3 删除索引
复制代码
DELETE /java06

3.2 映射(Type)管理

ES 6.x 后弱化 Type 概念(7.0 移除),Type 可类比数据库的 "表",用于定义 Document 的字段结构:

3.2.1 创建映射
复制代码
# POST /索引名/类型名/_mapping
POST /java06/course/_mapping
{
  "properties": {
     "name": { "type": "text" },        # 文本类型(可分词)
     "description": { "type": "text" }, # 文本类型
     "studymodel": { "type": "keyword" }# 关键字类型(不可分词)
  }
}
3.2.2 查询映射
复制代码
GET /java06/course/_mapping

3.3 文档(Document)管理

Document 类比数据库的 "行",是 ES 的最小数据单元:

3.3.1 创建文档
复制代码
# 方式1:手动指定ID(PUT)
PUT /java06/course/2
{
  "name":"php从入门到放弃",
  "description":"php是世界上最好的语言",
  "studymodel":"201001"
}

# 方式2:自动生成ID(POST)
POST /java06/course
{
  "name":".net从入门到放弃",
  "description":".net程序员谁都不服",
  "studymodel":"201003"
}
3.3.2 查询文档
复制代码
# 根据ID查询
GET /java06/course/1

# 全文检索(查询name包含"门"的文档)
GET /java06/course/_search?q=name:门

# 查询所有文档
GET /java06/course/_search
3.3.3 删除文档
复制代码
DELETE /java06/course/3

注意:ES 删除文档并非立即物理删除,而是标记为deleted,后续异步清理(保证近实时性能)。

3.4 核心机制:Document Routing

文档写入时,ES 通过以下算法路由到指定分片:

复制代码
shard = hash(文档ID) % 主分片数

主分片数不可修改:若修改主分片数,路由算法结果变化,导致无法找到原文档。

四、IK 分词器(中文分词解决方案)

4.1 原生分词器问题

ES 默认分词器对中文仅做 "单字分词"(例如 "测试" 拆分为 "测""试"),无法满足中文检索需求,需安装 IK 分词器。

4.2 安装 IK 分词器

  1. 下载对应版本:https://github.com/medcl/elasticsearch-analysis-ik/releases
  2. 解压到 ES 的plugins/ik目录;
  3. 重启 ES。

4.3 分词模式测试

4.3.1 ik_smart(粗粒度分词)
复制代码
POST /_analyze
{
  "text":"中华人民共和国人民大会堂",
  "analyzer":"ik_smart"
}
# 结果:["中华人民共和国", "人民大会堂"]
4.3.2 ik_max_word(细粒度分词)
复制代码
POST /_analyze
{
  "text":"中华人民共和国人民大会堂",
  "analyzer":"ik_max_word"
}
# 结果:["中华人民共和国", "中华人民", "中华", "华人", "人民大会堂", "人民", ...]

4.4 自定义词库

  1. plugins/ik/config目录新建my.dic(UTF-8 无 BOM 格式),添加自定义词汇;

  2. 编辑IKAnalyzer.cfg.xml,引入自定义词库:

    XML 复制代码
    <properties>
      <comment>IK Analyzer 扩展配置</comment>
      <entry key="ext_dict">my.dic</entry>
    </properties>
  3. 重启 ES 生效。

五、Field 字段详解

5.1 核心属性

属性 作用
type 字段类型(text/keyword/date/numeric 等)
analyzer 索引时分词器(如 ik_max_word)
search_analyzer 搜索时分词器(如 ik_smart,提高精准度)
index 是否索引(true/false,false 则无法搜索)
_source 是否存储原始字段(可通过 includes/excludes 筛选字段)

5.2 常用字段类型

5.2.1 text(文本类型)

适用于全文检索,需指定分词器:

XML 复制代码
"name": {
  "type": "text",
  "analyzer":"ik_max_word",    # 索引时分词(细粒度)
  "search_analyzer":"ik_smart" # 搜索时分词(粗粒度)
}
5.2.2 keyword(关键字类型)

不可分词,适用于精准匹配(如手机号、邮编)、排序、聚合:

XML 复制代码
"studymodel": {
  "type": "keyword"
}
5.2.3 date(日期类型)

支持自定义格式,适用于排序:

XML 复制代码
"timestamp": {
  "type": "date",
  "format": "yyyy-MM-dd||yyyy-MM-dd HH:mm:ss"
}
5.2.4 numeric(数值类型)

支持 float/int/long 等,适用于排序、区间搜索:

XML 复制代码
"price": {
  "type": "float"
}

六、Spring Boot 整合 ElasticSearch

6.1 客户端选择

  • TransportClient:传统客户端,8.0 废弃;
  • RestHighLevelClient:官方推荐,基于 RESTful API,功能完善。

6.2 工程搭建

6.2.1 pom.xml 依赖
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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.2.RELEASE</version>
    </parent>

    <groupId>com.powershop</groupId>
    <artifactId>springboot_elasticsearch</artifactId>
    <version>1.0-SNAPSHOT</version>
    
    <!-- 统一ES版本 -->
    <properties>
        <elasticsearch.version>6.2.3</elasticsearch.version>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- ES高级客户端 -->
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>${elasticsearch.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>
6.2.2 application.yml 配置
XML 复制代码
spring:
  elasticsearch:
    rest:
      uris:
        - http://192.168.204.132:9200 # ES服务地址
6.2.3 启动类
java 复制代码
package com.powershop;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ElasticsearchApp {
	public static void main(String[] args) {
		SpringApplication.run(ElasticsearchApp.class, args);
	}
}

6.3 索引操作示例

java 复制代码
package com.powershop.test;

import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
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.test.context.junit4.SpringRunner;

import java.io.IOException;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = ElasticsearchApp.class)
public class IndexOperationTest {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    /**
     * 创建索引+映射
     */
    @Test
    public void createIndex() throws IOException {
        // 1. 创建索引请求
        CreateIndexRequest request = new CreateIndexRequest("java06");

        // 2. 设置索引参数(分片/副本)
        String settings = "{\n" +
                "  \"number_of_shards\": 2,\n" +
                "  \"number_of_replicas\": 0\n" +
                "}";
        request.settings(settings, XContentType.JSON);

        // 3. 设置映射
        String mapping = "{\n" +
                "  \"_source\": {\n" +
                "    \"excludes\": [\"description\"]\n" +
                "  },\n" +
                "  \"properties\": {\n" +
                "    \"name\": {\n" +
                "      \"type\": \"text\",\n" +
                "      \"analyzer\": \"ik_max_word\",\n" +
                "      \"search_analyzer\": \"ik_smart\"\n" +
                "    },\n" +
                "    \"description\": {\n" +
                "      \"type\": \"text\",\n" +
                "      \"analyzer\": \"ik_max_word\",\n" +
                "      \"search_analyzer\": \"ik_smart\"\n" +
                "    },\n" +
                "    \"studymodel\": {\n" +
                "      \"type\": \"keyword\"\n" +
                "    },\n" +
                "    \"price\": {\n" +
                "      \"type\": \"float\"\n" +
                "    }\n" +
                "  }\n" +
                "}";
        request.mapping("course", mapping, XContentType.JSON);

        // 4. 执行创建
        CreateIndexResponse response = restHighLevelClient.indices().create(request);

        // 5. 打印结果
        System.out.println("索引创建成功:" + response.isAcknowledged());
    }
}

6.4 文档操作示例(新增 / 查询 / 删除)

java 复制代码
package com.powershop.test;

import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
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.test.context.junit4.SpringRunner;

import java.io.IOException;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = ElasticsearchApp.class)
public class DocumentOperationTest {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    /**
     * 新增文档
     */
    @Test
    public void addDocument() throws IOException {
        // 1. 构建文档数据
        String docJson = "{\n" +
                "  \"name\": \"SpringBoot整合ES实战\",\n" +
                "  \"description\": \"SpringBoot+ES实现全文检索\",\n" +
                "  \"studymodel\": \"202401\",\n" +
                "  \"price\": 99.0\n" +
                "}";

        // 2. 创建索引请求(索引名/类型名/文档ID)
        IndexRequest request = new IndexRequest("java06", "course", "1001");
        request.source(docJson, XContentType.JSON);

        // 3. 执行新增
        IndexResponse response = restHighLevelClient.index(request);

        // 4. 打印结果
        System.out.println("文档ID:" + response.getId());
        System.out.println("结果状态:" + response.getResult().name());
    }

    /**
     * 查询文档
     */
    @Test
    public void getDocument() throws IOException {
        // 1. 创建查询请求
        GetRequest request = new GetRequest("java06", "course", "1001");

        // 2. 执行查询
        GetResponse response = restHighLevelClient.get(request);

        // 3. 打印结果
        if (response.isExists()) {
            System.out.println("文档内容:" + response.getSourceAsString());
        } else {
            System.out.println("文档不存在");
        }
    }

    /**
     * 删除文档
     */
    @Test
    public void deleteDocument() throws IOException {
        // 1. 创建删除请求
        DeleteRequest request = new DeleteRequest("java06", "course", "1001");

        // 2. 执行删除
        DeleteResponse response = restHighLevelClient.delete(request);

        // 3. 打印结果
        System.out.println("删除状态:" + response.getResult().name());
    }
}

七、集群管理(扩展)

7.1 集群核心概念

  • 节点(Node):单个 ES 实例,分为主节点(Master)、数据节点(Data)、客户端节点(Client);
  • 分片(Shard):主分片(Primary)用于存储数据,副本分片(Replica)用于容灾和负载均衡;
  • 集群健康状态:green(所有分片可用)、yellow(副本分片不可用)、red(主分片不可用)。

7.2 集群配置要点

  1. 所有节点的cluster.name必须一致;
  2. 主节点需配置node.master: true
  3. 数据节点需配置node.data: true
  4. 集群发现地址discovery.zen.ping.unicast.hosts需包含所有主节点。

八、总结

ElasticSearch 作为高性能的全文检索引擎,核心优势在于分布式架构和倒排索引机制,结合 IK 分词器可完美解决中文检索需求。通过 Spring Boot 整合 RestHighLevelClient,能快速实现 ES 的索引、文档操作,满足企业级搜索场景的需求。实际应用中需注意分片规划、内存调优、分词器扩展等细节,确保 ES 集群稳定、高效运行。

相关推荐
陕西企来客6 分钟前
2026年7月AI搜索引擎优化案例深度解析
大数据·人工智能
LitchiCheng18 分钟前
DGX Spark部署ComfyUI(一键安装脚本)
大数据·分布式·spark
枕星而眠1 小时前
Git仓库基础用法
大数据·git·后端·elasticsearch·全文检索
智圣新创011 小时前
从10大数据集合规上报到数字驾驶舱落地 智圣新创职教中台对接解决方案的行业全域参考
大数据
数字新视界2 小时前
档案库房环境安全监控解决方案
大数据·运维·数据库·物联网·环境监控系统
thubier(段新建)9 小时前
owtb 3pl 面向城市配送物流企业需求V0.2
大数据·人工智能
jinggongszh11 小时前
智能硬件对接与系统落地:开发岗在制造现场的经验沉淀
大数据·人工智能
ZeekerLin11 小时前
AI 原生团队协作机制:角色、分工与工程文化变化
大数据·人工智能
ACP广源盛1392462567313 小时前
IX8024 PCIe4.0 交换芯片@ACP# RK3588:嵌入式 AI PC 标准化扩展方案
大数据·人工智能·分布式·单片机·嵌入式硬件