当前位置: 首页 > article >正文

ElasticSearch业务场景与面试题

以下是几个常见的 Elasticsearch 业务场景解决方案及面试题解析(含 Java 示例):


一、业务场景解决方案


场景 1:商品搜索与过滤

需求:电商平台需要支持多条件搜索(关键词、价格区间、分类、品牌)并按相关性排序。

解决方案

  1. Bool Query:组合 must(必须匹配)、should(加分项)、filter(无评分过滤)。
  2. Keyword 字段:分类/品牌等精确匹配字段使用 keyword 类型。
  3. 范围查询:价格区间使用 range 查询。
  4. 相关性排序:使用 TF-IDF 或 BM25 算法(ES 默认)。
// 使用 RestHighLevelClient(旧版)或 Java Client(新版)
SearchRequest request = new SearchRequest("products");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

BoolQueryBuilder boolQuery = QueryBuilders.boolQuery()
    .must(QueryBuilders.matchQuery("name", "手机")) // 关键词匹配
    .filter(QueryBuilders.rangeQuery("price").gte(1000).lte(5000)) // 价格过滤
    .filter(QueryBuilders.termQuery("category", "electronics")) // 分类精确匹配
    .should(QueryBuilders.matchQuery("brand", "Apple").boost(2.0f)); // 品牌加分

sourceBuilder.query(boolQuery)
    .sort(SortBuilders.scoreSort()) // 按相关性排序
    .from(0).size(10); // 分页

request.source(sourceBuilder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);

场景 2:日志分析与聚合

需求:分析系统日志中不同错误级别的出现次数。

解决方案

  1. Date Histogram:按时间区间聚合。
  2. Terms Aggregation:按错误级别分组统计。
  3. 索引设计:使用 @timestamp 字段记录日志时间。
SearchRequest request = new SearchRequest("logs");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

// 按错误级别聚合
TermsAggregationBuilder termsAgg = AggregationBuilders.terms("error_levels").field("level");
// 子聚合:按小时统计
DateHistogramAggregationBuilder dateHistogram = AggregationBuilders.dateHistogram("per_hour")
    .field("@timestamp").calendarInterval(DateHistogramInterval.HOUR);

termsAgg.subAggregation(dateHistogram);
sourceBuilder.aggregation(termsAgg);

request.source(sourceBuilder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);

// 解析聚合结果
Terms terms = response.getAggregations().get("error_levels");
for (Terms.Bucket bucket : terms.getBuckets()) {
    String level = bucket.getKeyAsString();
    DateHistogram dateHistogramAgg = bucket.getAggregations().get("per_hour");
    for (DateHistogram.Bucket hourBucket : dateHistogramAgg.getBuckets()) {
        System.out.println(level + " - " + hourBucket.getKeyAsString() + ": " + hourBucket.getDocCount());
    }
}

场景 3:搜索自动补全

需求:实现类似 Google 的搜索框自动补全功能。

解决方案

  1. Completion Suggester:专为自动补全设计的字段类型。
  2. N-gram 分词:支持部分匹配(如 “el” 匹配 “elasticsearch”)。
// 创建索引时定义补全字段
CreateIndexRequest request = new CreateIndexRequest("suggestions");
request.mapping(
    "{\n" +
    "  \"properties\": {\n" +
    "    \"suggest\": {\n" +
    "      \"type\": \"completion\"\n" +
    "    }\n" +
    "  }\n" +
    "}",
    XContentType.JSON
);
client.indices().create(request, RequestOptions.DEFAULT);

// 查询时使用 Suggest
SuggestBuilder suggestBuilder = new SuggestBuilder()
    .addSuggestion("my_suggestion",
        new CompletionSuggestionBuilder("suggest").prefix("el").size(5));

SearchSourceBuilder sourceBuilder = new SearchSourceBuilder().suggest(suggestBuilder);
SearchRequest searchRequest = new SearchRequest("suggestions").source(sourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

// 解析补全结果
CompletionSuggestion suggestion = response.getSuggest().getSuggestion("my_suggestion");
for (CompletionSuggestion.Entry.Option option : suggestion.getOptions()) {
    System.out.println(option.getText().string());
}

二、高频面试题


问题 1:Elasticsearch 如何保证数据一致性?
  • :ES 是近实时(NRT)系统,默认每秒刷新(refresh)一次。写入数据后需等待刷新或手动调用 refresh 才能搜索到。通过 wait_for 参数可强制等待变更可见:
    IndexRequest request = new IndexRequest("index")
        .source("field", "value")
        .setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL);
    

问题 2:如何处理深度分页的性能问题?
  • :避免使用 from + size(如 from=10000),改用 search_after
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder()
        .sort(SortBuilders.fieldSort("_id")) // 必须包含唯一排序字段
        .size(10);
    
    // 第一次查询
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    SearchHit[] hits = response.getHits().getHits();
    
    // 后续分页使用 search_after
    sourceBuilder.searchAfter(hits[hits.length - 1].getSortValues());
    

问题 3:如何同步 MySQL 数据到 Elasticsearch?
  • 方案
    1. Logstash JDBC Input:定时拉取 MySQL 数据。
    2. Binlog 监听:使用 Canal 或 Debezium 捕获 MySQL 变更,通过 Kafka 同步到 ES。
    3. 双写:应用层直接写入 MySQL 和 ES(需处理事务一致性)。

问题 4:如何优化 Elasticsearch 集群性能?
    • 硬件:使用 SSD、增加内存。
    • 索引设计:合理设置分片数(建议单个分片 10-50GB)、关闭不需要的字段 norms
    • 查询优化:避免通配符查询、使用 filter 替代 query 避免评分。
    • 冷热分离:将历史数据迁移到冷节点。

三、陷阱与注意事项

  1. 分片数不可变:创建索引时需预先规划分片数量。
  2. 脑裂问题:通过 discovery.zen.minimum_master_nodes(旧版)或 cluster.initial_master_nodes(新版)配置避免。
  3. 映射爆炸:限制动态映射,避免过多字段导致内存问题。

以上内容覆盖了常见场景和面试考点,结合 Java 代码可快速实现功能验证。


http://www.kler.cn/a/535366.html

相关文章:

  • 低代码提升交付效率的公式计算
  • NacosRce到docker逃逸实战
  • 【数据结构-Trie树】力扣720. 词典中最长的单词
  • 通过Python编写的中国象棋小游戏
  • mounted钩子函数里如何操作子组件的DOM?
  • 在线教程丨YOLO系列10年更新11个版本,最新模型在目标检测多项任务中达SOTA
  • PCA9685舵机控制板使用
  • OpenBMC:通过qemu-system-arm运行编译好的image
  • Windows编程:下载与安装 Visual Studio 2010
  • 深度学习 - 神经网络的原理
  • 基于多重算法的医院增强型50G全光网络设计与实践:构建智慧医疗新基石(下)
  • SpringAI介绍及本地模型使用方法
  • 【实战篇】巧用 DeepSeek,让 Excel 数据处理更高效
  • 【Ubuntu】ARM交叉编译开发环境解决“没有那个文件或目录”问题
  • DeepSeek模型构建与训练
  • 云计算——AWS Solutions Architect – Associate(saa)1、什么是云,AWS介绍
  • 网络爬虫js逆向之异步栈跟栈案例
  • Flink-WordCount源码解析
  • OpenGL学习笔记(十):初级光照:材质 Materials
  • DEEPSEKK GPT等AI体的出现如何重构工厂数字化架构:从设备控制到ERP MES系统的全面优化
  • 新星杯进化史:个人发起到CSDN官方支持,创作活动的新篇章
  • 从零手写Spring IoC容器(一):传统对象管理的困境与基础容器的实现
  • 参数3说明
  • Windows 中学习Docker环境准备3、在Ubuntu中安装Docker
  • Linux之守护进程,应用层协议
  • 【数据结构】_队列的结构与实现