news 2026/10/4 2:06:46

SpringBoot 整合 Elasticsearch 7.2.0 实战:索引构建与查询避坑指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpringBoot 整合 Elasticsearch 7.2.0 实战:索引构建与查询避坑指南

简介:面向SpringBoot开发者与需要将Elasticsearch升级到7.x的技术人员,这份PDF从版本兼容痛点切入,说明Spring Boot 2.1.x内置的spring-boot-starter-data-elasticsearch仍停留在ES 2.X,因此改用Spring-data-elasticsearch以适配7.2.0。文中对比transport与rest两种连接方式,明确rest通过HTTP API访问、官方推荐且后续版本长期支持,并给出完整实现:引入elasticsearch、elasticsearch-rest-client、elasticsearch-rest-high-level-client三个Maven依赖,在application.yml配置elasticsearch.ip地址,再通过配置类创建RestHighLevelClient,同时设置连接、Socket及连接请求超时时间为5分钟。资源为单个PDF文件,压缩包仅58KB,内容紧凑可直接阅读;已有6769人学习浏览,适合正在搭建ES客户端或排查版本兼容问题的读者,可对照示例快速复制配置并理解RestHighLevelClient初始化细节。

1. SpringBoot 整合 Elasticsearch 7.2.0:解决什么问题,值不值得做

一个搜索接口,数据库LIKE '%关键词%',数据量上了百万之后,查询耗时从几十毫秒涨到两秒,这是很多业务系统都会撞上的瓶颈。把关键词检索、日志分析、数据聚合这类需求交给 Elasticsearch,是后端团队最常走的路线。而 SpringBoot 整合 Elasticsearch 7.2.0,本质上就是用一套统一的方式,让你的应用能连接 ES、建索引、写数据、再组合查询条件检索数据。

7.2.0 这个版本号要单独拎出来说:它是 7.x 早期一个很稳定的节点,自带成熟的 RestHighLevelClient,对 JDK 版本要求也不苛刻。很多现存项目就是把它当基础设施用的,版本没有跟到 8.x,不是因为懒,而是因为够用且稳定。这套方案适合谁?适合正在维护老项目、需要给 SpringBoot 服务接一个搜索引擎,或者想避开 8.x/new Java Client 那套更复杂 API 的开发者。下面从环境、依赖、配置到查询把整条链路铺开,代码可以直接抄。

2. 版本选型:7.2.0 为什么值得锁,依赖怎么配才不打架

2.1 ES 7.x 的分水岭:type 移除与 RestHighLevelClient 成熟

ES 6.x 之前,一个索引里可以定义多个 type,6.x 开始逐步废弃,到 7.0 直接移除了多 type 的概念。这个改动对整合方是重大利好:索引结构从「索引 + 类型 + 文档」简化为「索引 + 文档」,Spring Data 层的映射逻辑也清爽了很多。如果你现在去搜旧资料,看到IndexRequest里还带 type(例如"doc"),那多半是 6.x 时代的写法,放到 7.2.0 会直接报错。

7.2.0 另一个价值点是 RestHighLevelClient 的 API 形态已经成型。这个客户端走 HTTP 协议,不需要持有 TransportClient 那套 TCP 端口和集群嗅探配置,只关心9200这一个 HTTP 端口。从使用角度讲,它对业务代码的侵入很小:你构造一个请求对象、执行、拿响应,剩下的连接管理、心跳探测、请求重试都由客户端处理。SpringBoot 项目里只需要一个配置类把它注册成 Bean,后续注入即可。

还有一点值得说:ES 7.2.0 安装包里自带一个 JDK,路径在安装目录的jdk文件夹下。这意味着你本地甚至不用单独配JAVA_HOME,直接跑启动脚本就能起来一个单机实例。对开发联调来说非常省事,这也是很多团队在本地把版本锁在 7.x 早期版本的原因。

2.2 先把依赖配齐:pom 与 SpringBoot 版本搭配

常见的做法是引入elasticsearch-rest-high-level-client,版本严格指定7.2.0。这里不要用 Spring Boot 的 dependencyManagement 去管理 ES 客户端版本,因为 SpringBoot 的 BOM 锁定的是 Spring Data Elasticsearch 的配套版本,和 ES 服务端不一定对齐。

<properties> <elasticsearch.version>7.2.0</elasticsearch.version> <java.version>1.8</java.version> </properties> <dependencies> <!-- SpringBoot Web 基础 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- ES 7.2.0 官方高版本客户端 --> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>${elasticsearch.version}</version> </dependency> <!-- 如果需要用 Spring Data 的 Repository 风格,再加这个 --> <!-- 注意:它会按自己的兼容策略绑 ES 版本,7.2.0 建议 SpringBoot 2.2.x ~ 2.4.x --> <!-- <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> --> </dependencies>

这段配置里有几个细节。java.version保持 1.8 是完全没问题的,7.2.0 官方支持 JDK 8,这点比 7.10+ 和 8.x 都亲民。注释里我也想提醒:spring-boot-starter-data-elasticsearch不是不能用,但它引入的 Spring Data Elasticsearch 版本会决定底层用哪种客户端、兼容哪个 ES 版本,版本匹配一旦错位就会出现诡异的序列化异常。我的经验是:新项目如果核心诉求是「把搜索做好」,直接用 RestHighLevelClient 最可控;如果团队习惯 Repository 风格,再考虑 starter,但必须对照兼容矩阵确认版本。

2.3 Windows 下启动 ES 7.2.0 的最小操作

本地开发基本都在 Windows 上,7.2.0 的启动方式和 Linux 一样,只要你把安装包解压到纯英文路径。

# Windows 命令行,进入 ES 安装目录 cd D:\elasticsearch-7.2.0 # 启动(前台运行,日志直接打在当前窗口) bin\elasticsearch.bat # 也可以用 -d 参数后台启动 bin\elasticsearch.bat -d

启动完成后,打开浏览器访问http://localhost:9200,看到一个包含"you_know_for_search"的 JSON 响应,就说明服务起来了。我一般会在config/elasticsearch.yml里先确认两个参数:cluster.name和http.port。默认http.port是 9200,如果被占用会启动失败,直接改端口或者关掉占用进程即可。还有一个在 Windows 下值得注意的点:ES 7.x 默认绑定的主机是localhost,如果你要用另一台机器连接,才需要改network.host,本地开发不用动。

3. 客户端配置与索引建库:从 yml 到 mapping 不踩坑

3.1 yml 里 ES 地址怎么设置

客户端配置不需要写死在 Java 代码里,放配置文件更符合 SpringBoot 习惯。下面是application.yml里的常见写法:

spring: elasticsearch: rest: uris: http://localhost:9200 connection-timeout: 5s read-timeout: 10s # 自定义配置:ES 在 SpringBoot 2.x 中常用自定义前缀 elasticsearch: host: localhost port: 9200 scheme: http username: elastic password: changeme

注意:这段 yml 里spring.elasticsearch.rest.uris是 Spring Boot 2.2+ 官方提供的配置项,可以少写很多 Java 配置。但 7.2.0 对应的 SpringBoot 版本对这个属性的支持程度不同,项目里更稳妥的方式是自己定义一个前缀(比如elasticsearch.host),然后用@ConfigurationProperties或@Value注入到配置类里,不依赖 SpringBoot 版本对你 ES 版本的兼容判断,这条路最稳。

3.2 写一个配置类把 RestHighLevelClient 交给容器

import org.apache.http.HttpHost; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestHighLevelClient; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class ElasticsearchClientConfig { @Value("${elasticsearch.host}") private String host; @Value("${elasticsearch.port}") private Integer port; @Value("${elasticsearch.scheme}") private String scheme; @Bean(destroyMethod = "close") public RestHighLevelClient restHighLevelClient() { // 三参数的 HttpHost 分别对应 地址、端口、协议 return new RestHighLevelClient( RestClient.builder(new HttpHost(host, port, scheme)) .setRequestConfigCallback(requestConfigBuilder -> requestConfigBuilder .setConnectTimeout(5000) .setSocketTimeout(60000)) .setMaxRetryTimeoutMillis(60000) ); } }

这个配置类有两个关键点。第一,destroyMethod = "close"是必须的:不声明的话,Spring 容器关闭时不会主动释放连接池,在频繁重启的应用里会积累 TIME_WAIT 连接。第二,setMaxRetryTimeoutMillis控制请求失败后的最大重试时间,建议不要设太大,否则 ES 集群抖动时接口会长时间阻塞。

3.3 索引创建与 mapping 设计:keyword 和 text 别搞混

索引是整个搜索系统的表结构,ES 的 mapping 定义了字段类型和分析方式。新手最容易在这翻车:把用户名字段设成 text,结果精确过滤时查不到;把描述字段设成 keyword,结果全文搜索搜不出来。常见的取舍如下表:

业务字段类型说明
idkeyword精确匹配、聚合、排序
titletext + keyword 子字段全文检索 + 精确过滤
contenttext全文检索,不参与聚合
createTimedate时间范围查询
statusinteger精确过滤
tagskeyword(数组)多值精确匹配

创建索引的代码要在应用启动时执行一次,不能每次请求都去建。我一般是在ApplicationRunner里做一次幂等创建。

import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; import org.elasticsearch.action.admin.indices.get.GetIndexRequest; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; @Component public class IndexInitializer implements ApplicationRunner { private final RestHighLevelClient client; public IndexInitializer(RestHighLevelClient client) { this.client = client; } @Override public void run(ApplicationArguments args) throws Exception { String index = "article"; // 先查索引是否存在,存在就直接跳过,避免重复创建报错 GetIndexRequest existsRequest = new GetIndexRequest(index); boolean exists = client.indices().exists(existsRequest, RequestOptions.DEFAULT); if (exists) { return; } CreateIndexRequest createRequest = new CreateIndexRequest(index); // 分片 1,副本 0:单机开发环境不浪费资源 createRequest.settings().put("index.number_of_shards", 1); createRequest.settings().put("index.number_of_replicas", 0); XContentBuilder mapping = XContentFactory.jsonBuilder() .startObject() .startObject("properties") .startObject("id") .field("type", "keyword") .endObject() .startObject("title") .field("type", "text") .startObject("fields") .startObject("raw") .field("type", "keyword") .endObject() .endObject() .endObject() .startObject("content") .field("type", "text") .field("analyzer", "standard") .endObject() .startObject("createTime") .field("type", "date") .field("format", "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis") .endObject() .endObject() .endObject(); createRequest.mapping(mapping); client.indices().create(createRequest, RequestOptions.DEFAULT); } }

这段代码里值得解释的是 title 字段的双重结构:text类型负责全文搜索,fields.raw子字段用keyword负责精确匹配和排序。如果你要对 title 做order by,ES 里是sort by title.raw,直接用title排序会报「fielddata is disabled」的错误。format那段我写了三种时间格式,epoch_millis是给毫秒时间戳用的,这样写入端传什么格式都能解析,算是少踩一个格式坑的经验。

4. 数据写入与组合查询:把业务数据同步进 ES 的最小闭环

4.1 批量写入:BulkRequest 比循环单条快多少

写入 ES 最忌讳的是写个for循环一条条IndexRequest,性能至少差一个数量级。正确姿势是攒一批再发BulkRequest。下面的代码从 MySQL 查出数据,批量写入 ES:

import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.bulk.BulkResponse; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.common.xcontent.XContentType; import java.util.List; import java.util.Map; public void bulkSync(List<Map<String, Object>> rows) throws Exception { // 批量请求对象,可以容纳多个子请求 BulkRequest bulkRequest = new BulkRequest(); for (Map<String, Object> row : rows) { // id 用业务主键,保证同一篇文档重复写入时是覆盖而不是新增 String docId = String.valueOf(row.get("id")); IndexRequest indexRequest = new IndexRequest("article") .id(docId) .source(row, XContentType.JSON); bulkRequest.add(indexRequest); } BulkResponse response = client.bulk(bulkRequest, RequestOptions.DEFAULT); if (response.hasFailures()) { // 打印第一条失败原因,方便定位 throw new RuntimeException(response.buildFailureMessage()); } }

三个参数值得记一下。row必须是 Map 结构,字段名和 mapping 里定义的要保持一致,否则会写入失败或字段类型不匹配;id用业务主键,这是数据同步幂等的关键;XContentType.JSON表示把 Map 序列化成 JSON 再发送。调用处建议每 5000 条调一次bulkSync,单批太大内存压力高,太小网络开销大,5000 是我在普通配置机器上试出比较稳的区间。

4.2 查询:BoolQueryBuilder 组合条件与高亮

ES 的查询 DSL 在 Java 里对应SearchSourceBuilder,一组boolQuery能覆盖绝大多数业务检索场景。下面是一个带关键词、状态过滤、时间范围和高亮的完整查询代码:

import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder; import org.elasticsearch.search.sort.SortOrder; public SearchResponse search(String keyword, Integer status, String startTime, String endTime, int page, int size) throws Exception { // 1. 布尔查询:must 是必须满足的,filter 不影响评分 BoolQueryBuilder boolQuery = QueryBuilders.boolQuery(); if (keyword != null && !keyword.isEmpty()) { // 多字段匹配:标题和正文,权重分配 2.0 和 1.0 boolQuery.must(QueryBuilders.multiMatchQuery(keyword, "title^2.0", "content")); } if (status != null) { boolQuery.filter(QueryBuilders.termQuery("status", status)); } if (startTime != null && endTime != null) { boolQuery.filter(QueryBuilders.rangeQuery("createTime") .gte(startTime).lte(endTime)); } // 2. 高亮:关键词用 <em> 标签包起来 HighlightBuilder highlightBuilder = new HighlightBuilder(); highlightBuilder.field("title").field("content"); highlightBuilder.preTags("<em>").postTags("</em>"); // 3. 组装请求 SearchSourceBuilder sourceBuilder = new SearchSourceBuilder() .query(boolQuery) .from((page - 1) * size) .size(size) .sort("createTime", SortOrder.DESC) .highlighter(highlightBuilder); SearchRequest searchRequest = new SearchRequest("article"); searchRequest.source(sourceBuilder); return client.search(searchRequest, RequestOptions.DEFAULT); }

这里最容易忽略的一个点:sort("createTime", SortOrder.DESC)要求createTime是 date 类型并且 mapping 里没被设为"enable": false。而高亮字段title必须是 text 类型,keyword 字段是不能高亮的。还有 filter 和 must 的区别:status 和时间范围用 filter,因为它们不参与相关性评分,ES 能走缓存,性能更好;关键词用 must,因为它影响打分排序。

4.3 分页与排序:from/size 的边界在哪

上面的代码用了from + size分页,这在小数据量下没问题,但它有硬边界:默认最多只能翻到第 10000 条。因为 ES 需要把每个分片上的前from + size条全部取出来再归并排序,翻页越深,性能开销越大。如果业务查询深翻页场景多,有两个替代方案:

// 方案一:search_after,适合实时滚动翻页 SearchSourceBuilder sourceBuilder = new SearchSourceBuilder() .query(boolQuery) .size(size) .sort("_shard_doc") .searchAfter(new Object[]{lastSortValue}); // 注意:searchAfter 必须配合排序使用,且排序字段值要唯一,否则翻页会丢数据
// 方案二:scroll,适合数据导出,不实时 SearchRequest searchRequest = new SearchRequest("article"); SearchSourceBuilder sourceBuilder = new SearchSourceBuilder() .query(boolQuery) .size(5000); searchRequest.source(sourceBuilder); searchRequest.scroll(TimeValue.timeValueMinutes(1L));

我的建议是:用户前台搜索用from + size限制最多翻 100 页;后台管理系统的导出任务用 scroll;实时增量同步用search_after。三种场景对应三种 API,不要混用。

5. 避坑:整合 7.2.0 最常见的 5 个翻车现场

5.1 现象:启动报错NoNodeAvailableException,连接被拒

原因可能是三个:第一,ES 服务没启动;第二,9200 端口没开放;第三,也是最高频的——你从旧项目里拷贝了 TransportClient 的配置,拿着 TCP 端口 9300 去连。这是 6.x 时代留下的「历史债务」:9300 是节点间通信端口,RestHighLevelClient 根本不用它。

解决:确认访问地址是http://你的IP:9200,不是9300。本地用curl http://localhost:9200先验证,通了再排查应用配置。另外,不要写cluster.name到 RestHighLevelClient 配置里,它只对 TransportClient 有意义,写了也不会报错,但会让后来接手的人误以为这是必需的。

5.2 现象:用spring-boot-starter-data-elasticsearch启动后,执行save()或findAll()报类型转换异常ClassCastException或ElasticsearchStatusException。

原因:Spring Data Elasticsearch 的版本和 ES 服务端版本不匹配。每个 SpringBoot 版本都绑定了特定版本的 Spring Data ES,而 Spring Data ES 内部对 ES 版本有硬性兼容要求。你的 SpringBoot 版本太新(比如 2.6+ 配 spring-data-elasticsearch 4.3.x),它默认发起的 REST 请求格式和 7.2.0 服务端不完全兼容,就会在反序列化阶段出问题。

解决:先查 Spring Data Elasticsearch 官方兼容矩阵,确认 SpringBoot 版本与 ES 7.2.0 的对应关系。最省心的还是绕开 starter,直接用第 2 章里的rest-high-level-client手动写 CRUD。这不算绕路,反而让你的业务代码不依赖 Spring Data 的实体映射,少掉一堆注解层面的黑匣子。

5.3 现象:Windows 下双击elasticsearch.bat一闪而过,日志文件里报"java.lang.IllegalStateException: path.home is not configured"或乱码错误。

原因:ES 安装路径包含中文或空格,比如D:\软件\elasticsearch-7.2.0。ES 的启动脚本对路径分隔符和特殊字符很敏感,路径一乱,解析配置就失败。

解决:把 ES 解压到纯英文路径,比如D:\dev\elasticsearch-7.2.0。顺手把config/jvm.options里-Xms1g和-Xmx1g调成512m,本地开发机器内存不足时,ES 会因为无法分配堆内存而静默退出。这一步是血泪经验:ES 启动失败很少在控制台直接报清晰错误,日志文件才是第一排查入口。

5.4 现象:中文关键词搜不到,英文能搜到。

原因:ES 7.2.0 自带的标准分析器 standard 对中文是逐字切分或者整句当成一个 token——实际上是按 Unicode 字符切分。比如搜索「整合」时,如果文档里是「SpringBoot 整合 ES」,分词结果是被拆散的,匹配不上。

解决:给公司业务索引装 IK 中文分词插件,或者在写入数据时用 HanLP 提前分词存进另一个 keyword 字段。具体方案放在第 6 章讲,但这里先给出定位思路:先用_analyzeAPI 看看分词结果。

curl -X POST "http://localhost:9200/_analyze?pretty" -H "Content-Type: application/json" -d '{"analyzer": "standard", "text": "SpringBoot整合Elasticsearch"}'

输出里如果看到每个汉字都是独立 token,就说明中文分词没有生效,查插件安装和索引 mapping 里的 analyzer 配置。

5.5 现象:SpringBoot 版本太高(比如 2.7.x / 3.x),pom 里引入elasticsearch-rest-high-level-client后互相冲突,Cannot resolve或运行期NoClassDefFoundError。

原因:SpringBoot 3.x 基于 Java 17,整个依赖体系对elasticsearch相关 jar 的坐标做了调整,而且高版本 SpringBoot 默认的spring-boot-dependenciesBOM 里可能引入了 ES 8.x 的客户端 jar,和你的 7.2.0 冲突。这也是「springboot版本太高」搜索热度高不下来的现实原因。

解决:不建议硬升。要么把项目整体迁到 SpringBoot 3 + 新 ES 客户端,那是另一个量级的改造;要么就在 2.x 里选一个合理版本(2.3.x ~ 2.5.x 区间)配 7.2.0。比起追版本,业务能稳定跑才是优先级。

6. 进阶玩法与验证方法:聚合统计、中文分词与数据恢复快照

6.1 聚合统计:按类目计数、按天统计

搜索之外,ES 的聚合语法在报表场景也很好用。下面的代码统计每个status下的文档数,并额外统计按天分布的文档数:

import org.elasticsearch.search.aggregations.AggregationBuilders; import org.elasticsearch.search.aggregations.BucketOrder; import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder; import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramAggregationBuilder; import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval; public void aggExample() { SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); sourceBuilder.size(0); // 只取聚合结果,不取文档列表 // 按状态字段分组,降序排列 TermsAggregationBuilder statusAgg = AggregationBuilders .terms("status_count") .field("status") .order(BucketOrder.count(false)); // 按天分桶:interval 指定时间间隔 DateHistogramAggregationBuilder dateAgg = AggregationBuilders .dateHistogram("date_count") .field("createTime") .calendarInterval(DateHistogramInterval.DAY); sourceBuilder.aggregation(statusAgg); sourceBuilder.aggregation(dateAgg); // 执行后从 response.getAggregations() 中解析桶结果 }

聚合里有个容易踩的坑:field("status")前提是该字段在 mapping 中的类型是 keyword 或 integer,且开启了"doc_values": true。text 字段默认不开 doc_values,直接对 text 做 terms 聚合会报Fielddata access is disabled。以前的解决方案是开启 fielddata(非常浪费堆内存),现在的方案是在 mapping 里为文本字段加 keyword 子字段,聚合用子字段。

6.2 中文分词:HanLP 在 SpringBoot 中的轻量整合思路

IK 分词插件需要在 ES 服务端安装插件包并重启节点,这个流程在生产和测试环境都要走运维。如果不想装插件,有一个轻量做法:写入时用 HanLP 分词,把分词结果放进一个独立字段,查询时也用同样逻辑分词去匹配。

import com.hankcs.hanlp.HanLP; import com.hankcs.hanlp.seg.common.Term; // 写入前处理 List<String> tokenList = new ArrayList<>(); List<Term> termList = HanLP.segment(content); for (Term term : termList) { // 过滤标点符号和虚词,保留名词、动词等实词 if (term.nature.toString().startsWith("n") || term.nature.toString().startsWith("v")) { tokenList.add(term.word); } } row.put("contentSeg", String.join(" ", tokenList));

这个方案的优点是业务代码完全可控,不依赖 ES 服务端安装任何插件;缺点是索引体积变大,而且查询需要和写入用同一套分词逻辑,否则匹配不上。HanLP 在 SpringBoot 中整合就成了一个普通 Bean,依赖里引入hanlp即可启动时自动加载模型,不需要额外配置。数据量不大时这个方案完全够用,我甚至觉得比部署 IK 插件更灵活。

6.3 快照恢复:把 ES 数据备份当成验收项

整合完 ES,第一件要验证的其实是灾难恢复能力,而不是花哨的查询功能。ES 的快照 API 支持把索引备份到共享目录或对象存储,恢复时一条命令完成。

# 1. 在 elasticsearch.yml 中声明仓库目录 # path.repo: ["D:/es_backup"] # 然后重启 ES 使配置生效 # 2. 注册一个快照仓库 curl -X PUT "http://localhost:9200/_snapshot/my_backup" -H "Content-Type: application/json" -d '{"type": "fs", "settings": {"location": "D:/es_backup"}}' # 3. 为所有索引创建一个快照 curl -X PUT "http://localhost:9200/_snapshot/my_backup/snapshot_20250101?wait_for_completion=true" # 4. 恢复指定索引 curl -X POST "http://localhost:9200/_snapshot/my_backup/snapshot_20250101/_restore" -H "Content-Type: application/json" -d '{"indices": "article", "rename_pattern": "(.+)", "rename_replacement": "article_restored"}'

恢复时建议使用rename_replacement还原成新索引名,确认数据完整后再切换别名或改回原名。我见过有人直接覆盖原索引恢复失败,导致数据双写的,名称混淆是快照恢复里最常见的失误。把这个功能在项目初期就验证一遍,比上线后数据丢了再研究「elasticsearch 恢复数据」要省心得多。

最后一个习惯分享:我现在做任何 ES 整合,第一步先确认服务端版本,第二步把客户端版本和服务端锁死,第三步才碰业务代码。版本错位的事故我处理过太多次,多数不是技术难题,而是依赖管理上想当然。7.2.0 配合 SpringBoot 2.x 是一套经过大量项目验证的组合,按这个思路走,无论你是一周内要交付搜索功能的开发,还是维护老项目想加搜索能力,方向都不会偏。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/4 2:01:19

BGP/OSPF互引路由环路成因与防环配置详解

简介&#xff1a;华为路由器三层路由防环专题第三部分聚焦BGP与OSPF协议互引场景下的路由环路问题&#xff0c;面向网络工程师、运维人员以及备考华为认证的读者&#xff0c;也可作为企业网与ISP边界组网设计的参考。资源以DeviceA发布的10.10.10.10/32路由为例&#xff0c;用四…

作者头像 李华
网站建设 2026/10/4 2:00:29

蟑螂检测数据集370张VOC+YOLO格式:小样本目标检测完整落地指南

简介&#xff1a;一套面向蟑螂目标检测任务的数据集&#xff0c;包含374张已标注图片&#xff0c;标注类别统一为蟑螂&#xff0c;适合计算机视觉学习者、算法工程师用于训练与评估主流目标检测模型&#xff0c;也适用于智能害虫监测、消杀机器人等实际视觉项目。压缩包共1124个…

作者头像 李华
网站建设 2026/10/4 1:59:41

@vueuse/rxjs 实战指南:在 Vue 3 组件中无缝集成 RxJS 响应式编程

前端 【免费下载链接】vueuse Collection of essential Vue Composition Utilities for Vue 3 项目地址&#xff1a; https://gitcode.com/gh_mirrors/vu/vueuse 点击查看 免费下载 vueuse/rxjs 是 VueUse 生态中面向 RxJS 的官方扩展包&#xff0c;它通过 7 个精心设计的组合…

作者头像 李华
网站建设 2026/10/4 1:59:01

GitHub Skills实战:任务驱动式技能训练与自动反馈机制

看到"skills"这个标题&#xff0c;我第一时间想到的是GitHub官方那个同名学习项目&#xff0c;但转念一想&#xff0c;这个词背后藏着的其实是一整套关于"技能到底应该怎么学"的命题。技术圈里聊技能&#xff0c;要么是零散的工具技巧&#xff0c;要么是收…

作者头像 李华
网站建设 2026/10/4 1:57:10

云边协同怎么讲才不空洞?从云计算到边缘计算的完整叙事线

简介&#xff1a;一份简要介绍云边协同的演示文稿&#xff0c;适合云计算与边缘计算的初学者快速建立整体认知。内容从云计算的定义开始&#xff0c;讲清编程模型、虚拟化、池化、数据存储与管理所代表的超级计算模式&#xff0c;以及广泛网络连入、快速弹性伸缩、计量付费服务…

作者头像 李华