client

ES Client 核心组件笔记

🏗️ 整体架构关系图

scss 复制代码
┌─────────────────────────────────────────────────────────────────┐
│                          业务层                                  │
│        OrderService, UserService, ProductService...             │
└─────────────────────────────────────────────────────────────────┘
                              ↓
┌─────────────────────────────────────────────────────────────────┐
│                       EsClient(统一入口)                        │
│  - 管理 ES 连接和配置                                             │
│  - 提供 SearchBuilder、Executor、AdminExecutor                   │
└─────────────────────────────────────────────────────────────────┘
                              ↓
        ┌─────────────────────┼─────────────────────┐
        │                     │                     │
   场景1:查询            场景2:写入           场景3:schema管理
        ↓                     ↓                     ↓
┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐
│ SearchBuilder    │  │ IndexExecutor    │  │ AdminExecutor    │
│ (查询构建器)       │  │ (批量执行器)       │  │ (管理执行器)      │
└──────────────────┘  └──────────────────┘  └──────────────────┘
        │                     │                     │
        │ build()             │ getProcessor()      │ createIndex()
        ↓                     ↓                     │ deleteIndex()
┌──────────────────┐  ┌──────────────────┐          │
│SearchSourceBuilder│ │   Processor      │          │
│ (ES 官方 DSL)     │  │  (请求收集器)     │          │
│ ├─ query         │  │ ├─ IndexProc     │          │
│ ├─ from/size     │  │ ├─ DeleteProc    │          │
│ ├─ sort          │  │ └─ UpdateProc    │          │
│ └─ ext (扩展)     │  └──────────────────┘          │
│    ├─ GroupBy    │          │                     │
│    └─ Timeout    │          │ 收集到               │
└──────────────────┘          ↓                     │
        │              ┌──────────────────┐          │
        │              │   ActionList     │          │
        │              │ [Req1, Req2...]  │          │
        │              └──────────────────┘          │
        │                     │                     │
        │                     │ execute()           │
        │                     ↓                     │
        │              ┌──────────────────┐          │
        │              │   BulkRequest    │          │
        │              │  (批量请求)       │          │
        │              └──────────────────┘          │
        │                     │                     │
        └─────────────────────┼─────────────────────┘
                              ↓
                    ┌──────────────────┐
                    │   FilterChain    │
                    │   (拦截器链)      │
                    │ ├─ Timeout       │ (调整超时)
                    │ ├─ CAT           │ (记录监控)
                    │ └─ Breaker       │ (熔断保护)
                    └──────────────────┘
                              ↓
                    ┌──────────────────┐
                    │RestHighLevelClient│
                    │  (高级 HTTP API)  │
                    │ ↓ 继承            │
                    │SimplifiedRest...  │ (企业优化)
                    └──────────────────┘
                              ↓
                    ┌──────────────────┐
                    │   RestClient     │
                    │  (底层 HTTP)      │
                    │ ├─ 连接池         │
                    │ ├─ 负载均衡       │
                    │ └─ 重试机制       │
                    └──────────────────┘
                              ↓
                        ES 服务器

📊 ES 官方 vs 企业封装架构对比

1️⃣ ES 官方架构

scss 复制代码
业务代码
  ↓
直接使用 RestHighLevelClient
  ↓
手动构建 SearchRequest/BulkRequest
  ↓
client.search() / client.bulk()
  ↓
RestClient (底层 HTTP)
  ↓
ES 服务器

官方使用方式:

java 复制代码
// 官方原生用法 - 直接操作
RestHighLevelClient client = new RestHighLevelClient(
    RestClient.builder(new HttpHost("localhost", 9200))
);

// 1. 搜索 - 手动构建所有参数
SearchRequest searchRequest = new SearchRequest("order_index");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.matchQuery("status", "paid"));
sourceBuilder.from(0);
sourceBuilder.size(10);
searchRequest.source(sourceBuilder);

SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

// 2. 批量写入 - 手动构建每个请求
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.add(new IndexRequest("order_index").id("001").source(...));
bulkRequest.add(new IndexRequest("order_index").id("002").source(...));
bulkRequest.add(new DeleteRequest("order_index", "003"));

BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);

特点:

  • 没有 Builder/Filter/Processor/Executor 这些概念
  • 没有 拦截器链(FilterChain)
  • 没有 统一的监控、超时配置、熔断
  • 没有 Processor 收集器(需要手动管理批量请求)
  • ✅ 只提供最基础的 RestHighLevelClient API

2️⃣ 企业封装架构

scss 复制代码
业务代码
  ↓
EsClient (统一入口)
  ├─ SearchBuilder (查询场景)
  ├─ Executor + Processor (批量写入场景)
  └─ AdminExecutor (管理场景)
  ↓
FilterChain (拦截器链)
  ├─ ESTimeoutConfigFilter (动态超时配置)
  ├─ ESCatFilter (监控埋点)
  └─ ESBreakerFilter (熔断保护)
  ↓
SimplifiedRestHighLevelClient (企业优化)
  ↓ 继承
RestHighLevelClient (官方客户端)
  ↓
RestClient (底层 HTTP)
  ↓
ES 服务器

企业封装使用方式:

java 复制代码
// 企业封装 - 更高层次的抽象
EsClient esClient = new EsClient(config);

// 1. 搜索 - 使用 SearchBuilder
SearchBuilder builder = new SearchBuilder(esClient)
    .addIndices("order_index")
    .setQuery(QueryBuilders.matchQuery("status", "paid"))
    .from(0).size(10)
    .setTag("search_order");  // 自动应用超时配置

SearchResponse response = builder.action();  // 自动经过 FilterChain

// 2. 批量写入 - 使用 Processor
IndexExecutor executor = esClient.getIndexExecutor();
IndexProcessor processor = executor.getIndexProcessor("order_index", "order_id");

// 收集数据(类似购物车)
processor.index(Map.of("order_id", "001", "amount", 100));
processor.index(Map.of("order_id", "002", "amount", 200));

// 一次性执行
BulkResult result = executor.execute(processor);

特点:

  • 提供 Builder/Filter/Processor/Executor 高层抽象
  • 提供 拦截器链(FilterChain)
  • 提供 统一的监控、超时配置、熔断
  • 提供 Processor 收集器(自动批量管理)
  • ✅ 在官方 API 基础上封装企业级能力

💡 使用场景说明

类比理解(ES vs 关系型数据库)

scss 复制代码
createIndex()           = CREATE TABLE(创建表结构)
deleteIndex()           = DROP TABLE(删除表)

IndexProcessor.index()  = INSERT(插入数据)
DeleteProcessor.delete()= DELETE(删除数据)

SearchBuilder.action()  = SELECT(查询数据)

完整示例:从创建到删除

java 复制代码
// 1. 创建索引(Schema)- 类似 CREATE TABLE
AdminExecutor adminExecutor = esClient.getAdminExecutor();
Map<String, Object> settings = Map.of(
    "number_of_shards", 3,
    "number_of_replicas", 1
);
Map<String, Object> mappings = Map.of(
    "properties", Map.of(
        "order_id", Map.of("type", "keyword"),
        "amount", Map.of("type", "long"),
        "create_time", Map.of("type", "date")
    )
);
adminExecutor.createIndex("order_index", settings, mappings);

// 2. 写入数据 - 类似 INSERT
IndexExecutor executor = esClient.getIndexExecutor();
IndexProcessor processor = executor.getIndexProcessor("order_index", "order_id");
processor.index(Map.of("order_id", "001", "amount", 100));
processor.index(Map.of("order_id", "002", "amount", 200));
executor.execute(processor);

// 3. 查询数据 - 类似 SELECT
SearchBuilder builder = new SearchBuilder(esClient)
    .addIndices("order_index")
    .setQuery(QueryBuilders.matchAllQuery());
SearchResponse response = builder.action();

// 4. 删除索引(Schema + 所有数据)- 类似 DROP TABLE
adminExecutor.deleteIndex("order_index");

🔍 核心组件详细关系

1. EsClient → SearchBuilder(搜索场景)

java 复制代码
// EsClient 是入口
EsClient esClient = new EsClient("localhost:9200", 9200);

// 创建 SearchBuilder
SearchBuilder searchBuilder = new SearchBuilder(esClient)
    .addIndices("order_index")
    .setQuery(QueryBuilders.matchQuery("status", "paid"));

// SearchBuilder 内部持有 EsClient 引用
public class SearchBuilder {
    private EsClient client;  // 持有 EsClient

    public SearchBuilder(EsClient client) {
        this.client = client;
    }
}

2. SearchBuilder → SearchSourceBuilder(DSL 构建)

java 复制代码
// SearchBuilder 构建 SearchSourceBuilder
public class SearchBuilder {

    public SearchRequest build() {
        // 1. 创建 ES 官方的 SearchSourceBuilder
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        // 2. 设置基础查询参数
        sourceBuilder.query(this.query);
        sourceBuilder.from(this.from);
        sourceBuilder.size(this.size);
        sourceBuilder.sort(this.sortBuilder);

        // 3. 添加扩展(ext)
        if (!extraSource.isEmpty()) {
            for (SearchExtBuilder extBuilder : extraSource) {
                sourceBuilder.ext(extBuilder);
            }
        }

        // 4. 创建 SearchRequest
        SearchRequest searchRequest = new SearchRequest(indices.toArray(new String[0]));
        searchRequest.source(sourceBuilder);

        return searchRequest;
    }
}

3. SearchSourceBuilder + SearchExtBuilder(扩展)

java 复制代码
// SearchSourceBuilder 包含扩展
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

// 添加基础查询
sourceBuilder.query(QueryBuilders.matchAllQuery());
sourceBuilder.from(0).size(10);

// 添加扩展
GroupByBuilder groupBy = new GroupByBuilder("user_id").setGroupSize(10);
SearchCommonExtBuilder commonExt = new SearchCommonExtBuilder().setFetchTimeout(500);

sourceBuilder.ext(Arrays.asList(groupBy, commonExt));

// 生成的完整 DSL
{
  "query": { "match_all": {} },
  "from": 0,
  "size": 10,
  "ext": {
    "group_by": {
      "field": "user_id",
      "group_size": 10
    },
    "common": {
      "fetch_timeout": 500
    }
  }
}

4. EsClient → IndexExecutor → Processor(批量操作场景)

java 复制代码
// EsClient 提供 Executor
EsClient esClient = new EsClient("localhost:9200", 9200);
IndexExecutor executor = esClient.getIndexExecutor();

// Executor 创建 Processor
IndexProcessor processor = executor.getIndexProcessor("order_index", "order_id");

// Processor 收集请求
processor.index(Map.of("order_id", "001", "amount", 100));
processor.index(Map.of("order_id", "002", "amount", 200));

// Executor 执行
BulkResult result = executor.execute(processor);

5. 完整的搜索流程

scss 复制代码
业务代码
  ↓
new SearchBuilder(esClient)
  ↓
SearchBuilder.setQuery()
SearchBuilder.from().size()
SearchBuilder.addExtraSource(groupBy)
  ↓
SearchBuilder.action()
  ↓
SearchBuilder.build()
  ├─ 创建 SearchSourceBuilder
  ├─ 设置 query, from, size
  ├─ 添加 ext (GroupByBuilder, CommonExtBuilder)
  └─ 创建 SearchRequest
  ↓
FilterChain.handle(searchBuilder)
  ├─ ESTimeoutConfigFilter(调整超时)
  └─ ESCatFilter(记录监控)
  ↓
SearchBuilder.doAsyncAction()
  ↓
client.getClient().searchAsync(searchRequest)
  ↓
RestHighLevelClient.search()
  ↓
RestClient.performRequest()
  ↓
HTTP 请求 → ES 服务器

6. 完整的批量操作流程

scss 复制代码
业务代码
  ↓
esClient.getIndexExecutor()
  ↓
executor.getIndexProcessor("order_index")
  ↓
processor.index(data1)  // 收集到 ActionList
processor.index(data2)  // 收集到 ActionList
processor.index(data3)  // 收集到 ActionList
  ↓
executor.execute(processor)
  ↓
executor.executeInternal(actionList.getActions())
  ├─ 创建 BulkRequest
  ├─ 添加所有 Request
  └─ 发送到 ES
  ↓
esClient.getClient().bulk(bulkRequest)
  ↓
RestHighLevelClient.bulk()
  ↓
RestClient.performRequest()
  ↓
HTTP 请求 → ES 服务器

📚 四大核心组件

1. Builder(构建器)- 构建请求

作用:构建请求参数,类似填写订单表单

SearchBuilder - 搜索请求构建器
java 复制代码
// 构建搜索请求
SearchBuilder searchBuilder = new SearchBuilder(esClient)
    .addIndices("order_index")                                   // 索引
    .setQuery(QueryBuilders.matchQuery("status", "paid"))        // 查询条件
    .from(0).size(10)                                            // 分页
    .addSort(SortBuilders.fieldSort("create_time"))              // 排序
    .docValueFields(Arrays.asList("order_id", "amount"));        // 返回字段

// 执行搜索
SearchResponse response = searchBuilder.action();
GroupByBuilder - 分组扩展构建器
java 复制代码
// 构建分组配置(生成 DSL 的 ext 部分)
GroupByBuilder groupBy = new GroupByBuilder("user_id")
    .setGroupSize(10)
    .setInShard(true);

searchBuilder.addExtraSource(groupBy);

// 生成的 DSL
{
  "query": { ... },
  "ext": {
    "group_by": {
      "field": "user_id",
      "group_size": 10,
      "in_shard": true
    }
  }
}
SearchCommonExtBuilder - 通用扩展构建器
java 复制代码
// 构建通用配置
SearchCommonExtBuilder commonExt = new SearchCommonExtBuilder()
    .setQueryTimeout(1000)
    .setFetchTimeout(500);

// 生成的 DSL
{
  "ext": {
    "common": {
      "query_timeout": 1000,
      "fetch_timeout": 500
    }
  }
}

关键点

  • ✅ Builder 负责构建请求
  • ✅ 使用链式调用,方便设置参数
  • ✅ 最终生成 ES DSL(通过 XContent 序列化)

2. Filter(拦截器)- 拦截请求过程

作用:在请求执行前后插入逻辑(监控、配置、熔断)

注意 :虽然叫 Filter,但实际是拦截器(Interceptor),不是过滤数据!

ESCatFilter - 监控拦截器
java 复制代码
public class ESCatFilter<T> implements AbstractFilter<T> {

    @Override
    public TracerActionFuture<T> filter(SearchBuilder searchBuilder, FilterHandler<T> nextHandler) {
        // ⭐ 拦截点 1:请求前
        Stopwatch stopwatch = Stopwatch.createStarted();
        Cat.logMetricForCount("es.search.store.field." + appkey, tags);  // 记录监控

        // ⭐ 继续执行
        TracerActionFuture<T> future = nextHandler.handle(searchBuilder);

        // ⭐ 拦截点 2:请求后(异步回调)
        future.addListener(new ActionListener<T>() {
            public void onResponse(T object) {
                long consume = stopwatch.elapsed(TimeUnit.MILLISECONDS);
                Cat.newCompletedTransactionWithDuration(...);  // 记录耗时
            }

            public void onFailure(Exception e) {
                Cat.newTransaction(...).setStatus(e);  // 记录错误
            }
        });

        return future;
    }
}

功能

  • ✅ 记录监控指标(使用了哪些字段)
  • ✅ 记录执行时间
  • ✅ 记录错误信息
  • ❌ 不修改请求和响应
ESTimeoutConfigFilter - 超时配置拦截器
java 复制代码
public class ESTimeoutConfigFilter<T> implements AbstractFilter<T> {

    @Override
    public TracerActionFuture<T> filter(SearchBuilder searchBuilder, FilterHandler<T> nextHandler) {
        // ⭐ 从配置中心读取超时配置
        TimeoutInfo timeout = getTimeout(appkey, tag);

        if (timeout != null) {
            // ⭐ 动态调整超时时间
            searchBuilder.setTimeout(timeout.getClient());        // 客户端超时
            searchBuilder.setServerTimeout(timeout.getServer());  // 服务端超时
            searchBuilder.setFetchTimeout(timeout.getFetch());    // Fetch 超时
        }

        // ⭐ 继续执行(使用新的超时配置)
        return nextHandler.handle(searchBuilder);
    }
}

功能

  • ✅ 从配置中心读取超时配置
  • ✅ 动态调整超时时间
  • ✅ 支持多级配置(tag > appkey)
  • ✅ 支持动态修改(不用重启)
FilterChain - 拦截器链
java 复制代码
public class FilterChain {
    // 默认的拦截器链
    public static final FilterHandler<?> DEFAULT_FILTER_HANDLER = actionDefaultAsyncFilter();

    private static <T> FilterHandler<T> actionDefaultAsyncFilter() {
        // 1. 最终的处理器:执行实际的搜索
        FilterHandler<T> actualHandler = searchBuilder -> searchBuilder.doAsyncAction();

        // 2. 拦截器列表
        List<AbstractFilter<T>> filterList = Lists.newArrayList();
        filterList.add(new ESCatFilter<>());           // 监控拦截器
        filterList.add(new ESTimeoutConfigFilter<>()); // 超时配置拦截器

        // 3. 构建拦截器链(责任链模式)
        return InvokeChainBuilder.buildInvokeChain(actualHandler, filterList);
    }
}

执行流程

scss 复制代码
请求开始
  ↓
ESTimeoutConfigFilter(调整超时配置)
  ↓
ESCatFilter(记录监控)
  ↓
doAsyncAction()(实际执行)
  ↓
响应返回(原路返回)
  ↓
ESCatFilter(记录耗时)

关键点

  • ✅ Filter 是拦截器,不是过滤器
  • ✅ 在请求执行前后插入逻辑
  • ✅ 使用责任链模式
  • ❌ 不过滤数据,不修改结果

3. Processor(处理器)- 收集请求

作用:收集多个 CRUD 请求,统一批量执行(类似购物车)

BulkProcessor - 基类
java 复制代码
public class BulkProcessor {
    protected EsClient esClient;
    protected String index;
    protected String idField;
    protected String routingField;

    // ⭐ 核心:请求列表(购物车)
    protected ActionList actionList = new ActionList();

    public ActionList getActionList() {
        return actionList;
    }
}
IndexProcessor - 新增请求收集器
java 复制代码
public class IndexProcessor extends BulkProcessor {

    // ⭐ 收集单条数据(往购物车放东西)
    public boolean index(Map<String, Object> data) {
        // 1. 构建 IndexRequest
        IndexRequest request = getIndexBuilderByMap(data);

        // 2. 添加到 actionList(只是收集,不执行!)
        actionList.addAction(request);

        return actionList.hasFailure();
    }

    // ⭐ 批量收集数据
    public boolean bulkIndex(List<Map<String, Object>> datas) {
        for (Map<String, Object> data : datas) {
            IndexRequest request = getIndexBuilderByMap(data);
            actionList.addAction(request);  // 只是收集
        }
        return actionList.hasFailure();
    }
}
DeleteProcessor - 删除请求收集器
java 复制代码
public class DeleteProcessor extends BulkProcessor {

    // ⭐ 收集单个删除请求
    public boolean delete(String id) {
        DeleteRequest request = new DeleteRequest(index, id);
        actionList.addAction(request);  // 只是收集
        return true;
    }

    // ⭐ 批量收集删除请求
    public boolean bulkDelete(List<String> deleteIds) {
        for (String id : deleteIds) {
            DeleteRequest request = new DeleteRequest(index, id);
            actionList.addAction(request);  // 只是收集
        }
        return actionList.hasFailure();
    }
}
UpdateProcessor - 更新请求收集器
java 复制代码
public class UpdateProcessor extends BulkProcessor {

    // ⭐ 收集更新请求
    public boolean update(Map<String, Object> data) {
        UpdateRequest request = buildUpdateRequest(data);
        actionList.addAction(request);  // 只是收集
        return true;
    }
}

关键点

  • ✅ Processor 是请求收集器(购物车)
  • ✅ 只收集请求,不执行
  • ✅ 通过 Executor 统一批量执行
  • ✅ 减少网络请求,提升性能

4. Executor(执行器)- 执行操作

作用:分配任务,执行批量操作(类似收银员结账)

IndexExecutor - 批量操作执行器
java 复制代码
public class IndexExecutor {
    private EsClient esClient;

    // ⭐ 创建 Processor(拿购物车)
    public IndexProcessor getIndexProcessor(String index) {
        return new IndexProcessor(esClient, index);
    }

    public DeleteProcessor getDeleteProcessor(String index) {
        return new DeleteProcessor(esClient, index);
    }

    public UpdateProcessor getUpdateProcessor(String index, String idField) {
        return new UpdateProcessor(esClient, index, idField);
    }

    // ⭐ 执行 Processor 中收集的操作(结账)
    public BulkResult execute(BulkProcessor bulkProcessor) {
        // 1. 从 Processor 获取收集的操作列表
        ActionList actionList = bulkProcessor.getActionList();
        List<DocWriteRequest<?>> requestList = actionList.getActions();

        // 2. 真正执行这些操作
        BulkResult bulkResult = executeInternal(requestList);

        return bulkResult;
    }

    // ⭐ 内部执行方法 - 真正发送请求到 ES
    public BulkResult executeInternal(List<DocWriteRequest<?>> requestList) {
        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.add(requestList);  // 添加所有请求

        // ⭐ 真正发送 HTTP 请求到 ES
        BulkResponse bulkResponse = esClient.getClient().bulk(bulkRequest, bulkRequestOptions);

        // 处理结果
        BulkResult result = new BulkResult();
        result.setTotal(bulkRequest.numberOfActions());

        if (bulkResponse.hasFailures()) {
            // 记录失败
            for (BulkItemResponse item : bulkResponse) {
                if (item.isFailed()) {
                    result.getServerErrorList().put(item.getId(), item.getFailureMessage());
                }
            }
        }

        return result;
    }
}
AdminExecutor - 管理操作执行器
java 复制代码
public class AdminExecutor {
    private EsClient esClient;

    // 创建索引
    public CreateIndexResponse createIndex(String index, Map<String, Object> settings) {
        CreateIndexRequest request = new CreateIndexRequest(index).settings(settings);
        return esClient.getClient().indices().create(request, RequestOptions.DEFAULT);
    }

    // 删除索引
    public AcknowledgedResponse deleteIndex(String index) {
        DeleteIndexRequest request = new DeleteIndexRequest(index);
        return esClient.getClient().indices().delete(request, RequestOptions.DEFAULT);
    }

    // 查看集群版本
    public Version getClusterVersion() {
        return esClient.getClient().info(RequestOptions.DEFAULT).getVersion();
    }
}

关键点

  • ✅ Executor 是真正的执行者
  • ✅ 创建 Processor(拿购物车)
  • ✅ 执行 Processor 中的操作(结账)
  • ✅ 发送 HTTP 请求到 ES

🔄 完整工作流程

场景 1:搜索操作

java 复制代码
// 1. Builder 构建请求
SearchBuilder builder = new SearchBuilder(esClient)
    .addIndices("order_index")
    .setQuery(QueryBuilders.matchQuery("status", "paid"))
    .from(0).size(10);

// 2. 执行搜索(自动经过 FilterChain)
SearchResponse response = builder.action();

// 内部流程:
// builder.action()
//   → FilterChain.DEFAULT_FILTER_HANDLER.handle(builder)
//     → ESTimeoutConfigFilter.filter()  // 调整超时配置
//       → ESCatFilter.filter()          // 记录监控
//         → builder.doAsyncAction()     // 实际执行
//           → 发送 HTTP 请求到 ES

场景 2:批量新增

java 复制代码
// 1. 获取 Executor
IndexExecutor executor = esClient.getIndexExecutor();

// 2. 创建 Processor(拿购物车)
IndexProcessor processor = executor.getIndexProcessor("order_index", "order_id");

// 3. 收集数据(往购物车放东西)
processor.index(Map.of("order_id", "001", "amount", 100));  // 只是收集
processor.index(Map.of("order_id", "002", "amount", 200));  // 只是收集
processor.index(Map.of("order_id", "003", "amount", 300));  // 只是收集

// 此时:actionList = [IndexRequest1, IndexRequest2, IndexRequest3]
// ⭐ 还没有发送任何 HTTP 请求!

// 4. 批量执行(结账)
BulkResult result = executor.execute(processor);  // ⭐ 一次性发送所有请求

// 5. 检查结果
System.out.println("总数: " + result.getTotal());    // 3
System.out.println("成功: " + result.getSuccess());  // 3
System.out.println("失败: " + result.getFail());     // 0

场景 3:批量删除

java 复制代码
// 1. 获取 Executor
IndexExecutor executor = esClient.getIndexExecutor();

// 2. 创建 Processor
DeleteProcessor processor = executor.getDeleteProcessor("order_index");

// 3. 收集删除请求
processor.delete("order_001");  // 只是收集
processor.delete("order_002");  // 只是收集
processor.delete("order_003");  // 只是收集

// 4. 批量执行
BulkResult result = executor.execute(processor);

📊 组件对比表

组件 作用 类比 何时执行
Builder 构建请求参数 订单表单 构建时
Filter 拦截请求过程 安检门/摄像头 请求前后
Processor 收集请求 购物车 收集时(不执行)
Executor 执行操作 收银员 execute() 时

🎯 关键理解

1. Builder vs Processor

java 复制代码
// Builder:用于搜索(直接执行)
SearchBuilder builder = new SearchBuilder(esClient)
    .setQuery(...)
    .from(0).size(10);
SearchResponse response = builder.action();  // 直接执行

// Processor:用于批量操作(先收集,后执行)
IndexProcessor processor = executor.getIndexProcessor("order_index");
processor.index(data1);  // 收集
processor.index(data2);  // 收集
executor.execute(processor);  // 执行

2. Filter 不是过滤器

java 复制代码
// ❌ 错误理解:Filter 过滤数据
// Filter 不会过滤掉任何数据

// ✅ 正确理解:Filter 是拦截器
// Filter 在请求执行前后插入逻辑(监控、配置、熔断)
// 不修改请求和响应

3. Processor 的批量优势

java 复制代码
// ❌ 传统方式:1000 次 HTTP 请求
for (String id : deleteIds) {  // 1000 个 ID
    esClient.delete(new DeleteRequest("order_index", id));
}
// 耗时:约 10 秒

// ✅ Processor 方式:1 次 HTTP 请求
DeleteProcessor processor = executor.getDeleteProcessor("order_index");
for (String id : deleteIds) {  // 1000 个 ID
    processor.delete(id);  // 只是收集
}
executor.execute(processor);  // 一次性发送
// 耗时:约 100ms
// 性能提升:100 倍!

4. XContent 序列化

java 复制代码
// Builder 通过 XContent 生成 DSL
GroupByBuilder groupBy = new GroupByBuilder("user_id").setGroupSize(10);

XContentBuilder builder = XContentFactory.jsonBuilder();
groupBy.toXContent(builder, ToXContent.EMPTY_PARAMS);

// 生成的 JSON:
{
  "group_by": {
    "field": "user_id",
    "group_size": 10
  }
}

💡 最佳实践

1. 搜索操作

java 复制代码
// 使用 SearchBuilder
SearchBuilder builder = new SearchBuilder(esClient)
    .addIndices("order_index")
    .setQuery(QueryBuilders.matchQuery("status", "paid"))
    .from(0).size(10)
    .setTag("search_order");  // 设置 tag,用于超时配置

SearchResponse response = builder.action();

2. 批量操作

java 复制代码
// 使用 Processor + Executor
IndexExecutor executor = esClient.getIndexExecutor();
IndexProcessor processor = executor.getIndexProcessor("order_index", "order_id");

// 收集数据
for (Order order : orders) {
    processor.index(order.toMap());
}

// 批量执行
BulkResult result = executor.execute(processor);

3. 混合操作

java 复制代码
// 同时新增和删除
IndexProcessor indexProcessor = executor.getIndexProcessor("order_index", "order_id");
DeleteProcessor deleteProcessor = executor.getDeleteProcessor("order_index");

// 收集新增
indexProcessor.bulkIndex(newOrders);

// 收集删除
deleteProcessor.bulkDelete(deleteIds);

// 一起执行
BulkResult result = executor.execute(indexProcessor, deleteProcessor);

📝 总结

组件 核心职责 关键方法
Builder 构建请求 setQuery(), from(), size(), action()
Filter 拦截监控 filter()
Processor 收集请求 index(), delete(), update()
Executor 执行操作 getProcessor(), execute()

记住

  • Builder = 订单表单(构建请求)
  • Filter = 安检门(拦截监控)
  • Processor = 购物车(收集请求)
  • Executor = 收银员(批量执行)
相关推荐
苏三的开发日记3 小时前
RocketMQ面试题
后端
SimonKing3 小时前
【开发者必备】Spring Boot 2.7.x:WebMvcConfigurer配置手册来了(六)!
java·后端·程序员
xiaoye20183 小时前
mybatis-plus 浅析
后端
qincloudshaw3 小时前
java中实现对象深克隆的四种方式
后端
代码哈士奇4 小时前
简单使用Nest+Nacos+Kafka实现微服务
后端·微服务·nacos·kafka·nestjs
一 乐4 小时前
商城推荐系统|基于SprinBoot+vue的商城推荐系统(源码+数据库+文档)
前端·数据库·vue.js·spring boot·后端·商城推荐系统
golang学习记4 小时前
VMware 官宣 彻底免费:虚拟化新时代来临!
后端
绝无仅有4 小时前
某短视频大厂的真实面试解析与总结(一)
后端·面试·github
JavaGuide4 小时前
中兴开奖了,拿到了SSP!
后端·面试