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 集群稳定、高效运行。

相关推荐
元拓数智1 小时前
AI Agent 时代,企业数据治理底座如何支撑智能应用的安全与效率
大数据·人工智能·安全·数据治理·nl2sql·自然语言查询
Haibakeji1 小时前
AI如何串联官网小程序APP多端用户体验
大数据·apache
张祥前世界大同1 小时前
基于矢量光速螺旋时空的真空介电常数与引力常数统一关系(最终定稿版)
大数据·sqlite
Cx330❀1 小时前
从零实现一个 C++ 轻量级日志系统:原理与实践
大数据·linux·运维·服务器·开发语言·c++·搜索引擎
Mike117.1 小时前
GBase 8a 慢任务处理时 KILL 和 PROCESSLIST 的使用边界
大数据·数据库
Simon_lca1 小时前
2026 零售验厂生死线:Bon-Ton+Nordstrom+Williams Sonoma 三大巨头标准大 PK
大数据·人工智能·经验分享·数据分析·制造·零售
SEO_juper1 小时前
外贸独立站流量翻倍后的转化优化
大数据·前端·seo·geo·外贸独立站·谷歌优化·2026
兴通物联科技1 小时前
3C半导体DPM金属雕刻码扫码器技术解析——兴通物联硬件架构与算法优化
大数据·物联网·计算机视觉·硬件架构