SpringBoot集成Elasticsearch:嵌套文档查询实现指南

1. 前置条件
  • 依赖配置(pom.xml):

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    </dependency>
    

  • 索引映射示例(嵌套文档结构):

    {
      "properties": {
        "order_id": {"type": "keyword"},
        "items": {
          "type": "nested",  // 关键:声明为嵌套类型
          "properties": {
            "product_name": {"type": "text"},
            "quantity": {"type": "integer"}
          }
        }
      }
    }
    


2. 配置High Level Client
@Configuration
public class ElasticsearchConfig {
    
    @Bean
    public RestHighLevelClient client() {
        return new RestHighLevelClient(
            RestClient.builder(new HttpHost("localhost", 9200, "http"))
        );
    }
}


3. 嵌套文档查询实现
@Service
public class OrderSearchService {

    @Autowired
    private RestHighLevelClient client;

    public List<Order> searchNestedItems(String productName) throws IOException {
        // 1. 创建嵌套查询
        QueryBuilder nestedQuery = QueryBuilders.nestedQuery(
            "items",  // 嵌套字段路径
            QueryBuilders.matchQuery("items.product_name", productName),
            ScoreMode.None  // 评分模式
        );

        // 2. 构建搜索请求
        SearchRequest request = new SearchRequest("orders_index");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder()
            .query(nestedQuery)
            .size(10);
        request.source(sourceBuilder);

        // 3. 执行查询
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        // 4. 结果解析
        return Arrays.stream(response.getHits().getHits())
            .map(hit -> parseOrder(hit.getSourceAsString()))
            .collect(Collectors.toList());
    }

    private Order parseOrder(String source) {
        // JSON解析逻辑(使用Jackson/Gson)
    }
}


4. 关键参数说明
参数 作用
nestedQuery() 声明嵌套查询
"items" 嵌套字段的路径(需与映射定义一致)
ScoreMode 可选值:Avg(平均分)、Max(最高分)、Total(总分)、None(无评分)

5. 复杂查询示例(多条件嵌套)
// 组合查询:产品名包含"手机"且数量>2
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery()
    .must(QueryBuilders.matchQuery("items.product_name", "手机"))
    .must(QueryBuilders.rangeQuery("items.quantity").gt(2));

QueryBuilder nestedQuery = QueryBuilders.nestedQuery("items", boolQuery, ScoreMode.None);


6. 常见问题解决方案
  1. 查询无结果

    • 检查字段路径是否正确(区分./
    • 确认索引映射中字段定义为nested类型
  2. 性能优化

    // 添加路径过滤器
    nestedQuery.innerHit(new InnerHitBuilder()
        .setSize(5)  // 限制返回嵌套文档数量
    );
    

  3. 聚合嵌套文档

    AggregationBuilder aggregation = AggregationBuilders.nested("nested_items", "items")
        .subAggregation(AggregationBuilders.terms("product_count").field("items.product_name.keyword"));
    

注意:嵌套文档查询需要严格遵循Elasticsearch的嵌套数据模型,每个嵌套对象在内部作为独立文档存储,需使用nested查询保证查询原子性。

SpringBoot集成Elasticsearch:嵌套文档查询实现指南

1. 前置条件
  • 依赖配置(pom.xml):

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    </dependency>
    

  • 索引映射示例(嵌套文档结构):

    {
      "properties": {
        "order_id": {"type": "keyword"},
        "items": {
          "type": "nested",  // 关键:声明为嵌套类型
          "properties": {
            "product_name": {"type": "text"},
            "quantity": {"type": "integer"}
          }
        }
      }
    }
    


2. 配置High Level Client
@Configuration
public class ElasticsearchConfig {
    
    @Bean
    public RestHighLevelClient client() {
        return new RestHighLevelClient(
            RestClient.builder(new HttpHost("localhost", 9200, "http"))
        );
    }
}


3. 嵌套文档查询实现
@Service
public class OrderSearchService {

    @Autowired
    private RestHighLevelClient client;

    public List<Order> searchNestedItems(String productName) throws IOException {
        // 1. 创建嵌套查询
        QueryBuilder nestedQuery = QueryBuilders.nestedQuery(
            "items",  // 嵌套字段路径
            QueryBuilders.matchQuery("items.product_name", productName),
            ScoreMode.None  // 评分模式
        );

        // 2. 构建搜索请求
        SearchRequest request = new SearchRequest("orders_index");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder()
            .query(nestedQuery)
            .size(10);
        request.source(sourceBuilder);

        // 3. 执行查询
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        // 4. 结果解析
        return Arrays.stream(response.getHits().getHits())
            .map(hit -> parseOrder(hit.getSourceAsString()))
            .collect(Collectors.toList());
    }

    private Order parseOrder(String source) {
        // JSON解析逻辑(使用Jackson/Gson)
    }
}


4. 关键参数说明
参数 作用
nestedQuery() 声明嵌套查询
"items" 嵌套字段的路径(需与映射定义一致)
ScoreMode 可选值:Avg(平均分)、Max(最高分)、Total(总分)、None(无评分)

5. 复杂查询示例(多条件嵌套)
// 组合查询:产品名包含"手机"且数量>2
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery()
    .must(QueryBuilders.matchQuery("items.product_name", "手机"))
    .must(QueryBuilders.rangeQuery("items.quantity").gt(2));

QueryBuilder nestedQuery = QueryBuilders.nestedQuery("items", boolQuery, ScoreMode.None);


6. 常见问题解决方案
  1. 查询无结果

    • 检查字段路径是否正确(区分./
    • 确认索引映射中字段定义为nested类型
  2. 性能优化

    // 添加路径过滤器
    nestedQuery.innerHit(new InnerHitBuilder()
        .setSize(5)  // 限制返回嵌套文档数量
    );
    

  3. 聚合嵌套文档

    AggregationBuilder aggregation = AggregationBuilders.nested("nested_items", "items")
        .subAggregation(AggregationBuilders.terms("product_count").field("items.product_name.keyword"));
    

注意:嵌套文档查询需要严格遵循Elasticsearch的嵌套数据模型,每个嵌套对象在内部作为独立文档存储,需使用nested查询保证查询原子性。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐