一、ElasticSearch 核心认知
1.1 为什么选择 ElasticSearch?
在电商、资讯等平台的全文检索场景中,传统数据库的字段匹配查询无法满足 "模糊、多关键词、高并发" 的检索需求。ElasticSearch(ES)基于 Lucene 实现分布式全文检索,通过词元匹配(如 "北京天安门" 拆分为 "北京""天安门" 等词元),支持灵活的关键字检索,是 Github、电商平台等大规模检索场景的首选。
1.2 ES 核心特性
- 分布式架构:天然支持集群部署,高可用、高并发。
- RESTful API:提供简洁的 HTTP 接口操作索引 / 搜索,支持多语言客户端。
- 倒排索引:核心检索原理,从 "关键字→文档" 的映射,大幅提升检索效率。
- 实时性:近实时(NRT)检索,数据写入后秒级可查。
1.3 倒排索引原理
倒排索引是 ES 高效检索的核心,由三部分组成:
- Document:存储原始文档数据;
- 分词列表:文档内容分词后去重的词汇集合;
- 关联关系:每个分词与所属 Document 的映射。
例如检索 "quick brown" 时,ES 会匹配包含该分词的文档,并按匹配度排序,优先返回相关性更高的结果。
二、环境搭建(Linux)
2.1 环境要求
- JDK:1.8.0_131 及以上;
- 内存:至少 1.5G(ES 需 4096 + 线程池、262144 + 字节虚拟内存);
- 权限:禁止 root 启动,需创建普通用户;
- 内核:CentOS 内核 3.5+(CentOS6 需禁用相关插件)。
2.2 ES 安装步骤
(1)创建用户(避免 root 启动)
bash:
# 创建用户组
groupadd es
# 创建用户并设置密码
useradd admin
passwd admin
# 将用户加入组
usermod -G es admin
# 分配目录权限
chown -R admin:es /usr/upload
chown -R admin:es /usr/local
# 切换用户
su admin
(2)解压安装
bash:
# 解压到指定目录
tar -zxvf elasticsearch-6.2.3.tar.gz -C /usr/local
(3)核心配置
ES 配置文件位于config目录,关键文件:
- elasticsearch.yml(集群 / 节点配置):
yaml:
cluster.name: power_shop
node.name: power_shop_node_1
network.host: 0.0.0.0
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
http.cors.enabled: true
http.cors.allow-origin: /.*/
# CentOS6内核兼容
bootstrap.system_call_filter: false
- jvm.options(JVM 内存配置):
properties:
# 建议设置为物理内存的1/2,且两者相等
-Xms512m
-Xmx512m
(4)系统参数调优(root 用户操作)
解决文件 / 线程 / 虚拟内存限制:
bash:
# 1. 文件描述符限制
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
(5)启动与测试
bash:
# 后台启动
./elasticsearch -d
# 验证启动(浏览器访问)
http://192.168.204.132:9200
返回如下 JSON 表示启动成功:
json:
{
"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 安装(可视化管理)
Kibana 是 ES 的可视化工具,支持索引管理、DSL 语句调试:
- 解压安装(Windows/Linux 通用);
- 修改
config/kibana.yml:
yaml:
server.port: 5601
server.host: "0.0.0.0"
elasticsearch.url: http://192.168.61.135:9200
- 启动:
./bin/kibana,访问http://127.0.0.1:5601即可使用。
2.4 Head 插件(集群监控)
Head 是 ES 的集群监控插件,基于 Node.js 运行:
bash:
# 下载后启动
npm run start
# 访问
http://127.0.0.1:9100/
三、ES 快速入门(DSL 操作)
3.1 索引(Index)管理
索引相当于关系型数据库的 "库",核心操作:
(1)创建索引
json:
PUT /java06
{
"settings": {
"number_of_shards": 2, // 主分片数(不可修改)
"number_of_replicas": 1 // 副本数(可修改)
}
}
(2)修改索引(仅副本数)
json:
PUT /java06/_settings
{
"number_of_replicas" : 1
}
(3)删除索引
json:
DELETE /java06
3.2 映射(Mapping)管理
映射相当于 "表结构",定义字段类型、分词器等(ES6.x 后弱化 Type,7.0 移除):
(1)创建映射
json:
POST /java06/course/_mapping
{
"properties": {
"name": {
"type": "text", // 文本类型(分词)
"analyzer":"ik_max_word", // 索引时分词(细粒度)
"search_analyzer":"ik_smart" // 搜索时分词(粗粒度)
},
"studymodel": {
"type": "keyword" // 关键字类型(不分词)
},
"price": {
"type": "float" // 数值类型
},
"timestamp": {
"type": "date", // 日期类型
"format": "yyyy-MM-dd"
},
"pic": {
"type": "text",
"index": false // 不索引(不可检索)
}
}
}
3.3 文档(Document)管理
文档相当于 "表记录",核心操作:
(1)新增文档
json:
# 手动指定ID
PUT /java06/course/1
{
"name":"python从入门到放弃",
"description":"人生苦短,我用Python",
"studymodel":"201002",
"price":29.9,
"timestamp":"2024-01-01",
"pic":"250.jpg"
}
# 自动生成ID
POST /java06/course
{
"name":".net从入门到放弃",
"description":".net程序员谁都不服",
"studymodel":"201003"
}
(2)查询文档
json:
# 根据ID查询
GET /java06/course/1
# 全文检索
GET /java06/course/_search?q=name:放弃
# 条件检索(DSL)
GET /java06/course/_search
{
"query": {
"match": {
"name": "python"
}
}
}
(3)删除文档
json:
DELETE /java06/course/1
四、IK 分词器
4.1 分词器核心作用
ES 默认对中文按 "单字" 分词(如 "测试"→"测""试"),IK 分词器解决中文分词问题,支持:
ik_max_word:细粒度分词(如 "中华人民共和国"→"中华人民共和国""中华人民""中华" 等);ik_smart:粗粒度分词(如 "中华人民共和国"→"中华人民共和国")。
4.2 安装与测试
- 下载 IK 分词器(对应 ES 版本),解压到
plugins/ik目录,重启 ES; - 测试分词效果:
json:
POST /_analyze
{
"text":"中华人民共和国人民大会堂",
"analyzer":"ik_smart"
}
4.3 自定义词库
如需识别专有词汇(如 "动力优品"),可在 IK 的config目录新建my.dic(UTF-8 无 BOM 格式),添加自定义词汇,并修改IKAnalyzer.cfg.xml引入该词库。
五、Spring Boot 整合 ES
5.1 依赖配置
(1)pom.xml
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>
</dependency>
</dependencies>
</project>
(2)application.yml
yaml:
spring:
elasticsearch:
rest:
uris:
- http://192.168.204.132:9200
5.2 核心 API 实战
(1)创建索引 + 映射
java:
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 EsIndexTest {
@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" +
" \"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());
}
}
(2)新增文档
java:
java
// 新增文档
@Test
public void addDocument() throws IOException {
// 1. 构建文档数据
Map<String, Object> docMap = new HashMap<>();
docMap.put("name", "SpringCloud实战");
docMap.put("studymodel", "201001");
docMap.put("price", 39.9);
// 2. 创建索引请求
IndexRequest request = new IndexRequest("java06", "course", "3");
request.source(docMap, XContentType.JSON);
// 3. 执行新增
IndexResponse response = restHighLevelClient.index(request);
// 4. 打印结果
System.out.println("文档新增成功,ID:" + response.getId());
}
(3)检索文档
java:
java
// 检索文档
@Test
public void searchDocument() throws IOException {
// 1. 创建搜索请求
SearchRequest request = new SearchRequest("java06");
request.types("course");
// 2. 构建查询条件
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.matchQuery("name", "SpringCloud"));
request.source(sourceBuilder);
// 3. 执行搜索
SearchResponse response = restHighLevelClient.search(request);
// 4. 解析结果
SearchHits hits = response.getHits();
System.out.println("匹配总数:" + hits.getTotalHits());
for (SearchHit hit : hits) {
System.out.println("文档内容:" + hit.getSourceAsString());
}
}
六、核心总结
- ES 核心是倒排索引,适合全文检索、日志分析、监控等场景;
- 集群部署时,主分片数一旦设置不可修改,副本数可动态调整;
- 中文分词优先选择 IK 分词器,索引时细粒度、搜索时粗粒度兼顾召回率与精准度;
- Spring Boot 整合 ES 推荐使用 RestHighLevelClient,替代即将废弃的 TransportClient;
- 字段设计原则:根据 "是否检索、是否分词、是否排序" 选择类型(text/keyword/date/numeric)。
本文基于 ElasticSearch 6.2.3 版本编写,不同版本 API 略有差异,需注意版本兼容。