一、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 /java063.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 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:92005.2 核心 API 实战
(1)创建索引 + 映射
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:
// 新增文档 @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:
// 检索文档 @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 略有差异,需注意版本兼容。