You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在SpringBoot中实现Elasticsearch的Multi-Match搜索查询

将Elasticsearch多字段查询转换为SpringBoot Java实现

我已在Kibana中验证以下查询,可针对products索引搜索关键词"novel",匹配description、name、id、price字段:

GET products/_search
{
  "query": {
    "multi_match" : {
      "query":    "novel", 
      "fields": [ "description", "name","id" ,"price"] 
    }
  }
}

现需将该查询转换为SpringBoot项目的Java代码,以下是项目中现有Controller和ElasticSearchQuery类代码,请指导正确实现该搜索功能:


现有Controller类代码

package com.pixelTrice.elastic.search;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.List;

@RestController
public class ElasticSearchController {

    @Autowired
    private ElasticSearchQuery elasticSearchQuery;

    @PostMapping("/createOrUpdateDocument")
    public ResponseEntity<Object> createOrUpdateDocument(@RequestBody Product product) throws IOException {
          String response = elasticSearchQuery.createOrUpdateDocument(product);
        return new ResponseEntity<>(response, HttpStatus.OK);
    }

    @GetMapping("/getDocument")
    public ResponseEntity<Object> getDocumentById(@RequestParam String productId) throws IOException {
       Product product =  elasticSearchQuery.getDocumentById(productId);
        return new ResponseEntity<>(product, HttpStatus.OK);
    }

    @DeleteMapping("/deleteDocument")
    public ResponseEntity<Object> deleteDocumentById(@RequestParam String productId) throws IOException {
        String response =  elasticSearchQuery.deleteDocumentById(productId);
        return new ResponseEntity<>(response, HttpStatus.OK);
    }

    @GetMapping("/searchDocument")
    public ResponseEntity<Object> searchAllDocument() throws IOException {
        List<Product> products = elasticSearchQuery.searchAllDocuments();
        return new ResponseEntity<>(products, HttpStatus.OK);
    }
    @GetMapping("/searching")
    public ResponseEntity<Object> searching() throws IOException{
         List<Product> products = elasticSearchQuery.searching();
         return new ResponseEntity<>(products,HttpStatus.OK);
        
    }
}

现有ElasticSearchQuery类代码

package com.pixelTrice.elastic.search;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.core.*;
import co.elastic.clients.elasticsearch.core.search.Hit;

import org.apache.lucene.queryparser.flexible.core.builders.QueryBuilder;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Repository
public class ElasticSearchQuery {

    @Autowired
    private ElasticsearchClient elasticsearchClient;

    private final String indexName = "products";


    public String createOrUpdateDocument(Product product) throws IOException {

        IndexResponse response = elasticsearchClient.index(i -> i
                .index(indexName)
                .id(product.getId())
                .document(product)
        );
        if (response.result().name().equals("Created")) {
            return new StringBuilder("Document has been successfully created.").toString();
        } else if (response.result().name().equals("Updated")) {
            return new StringBuilder("Document has been successfully updated.").toString();
        }
        return new StringBuilder("Error while performing the operation.").toString();
    }

    public Product getDocumentById(String productId) throws IOException {
        Product product = null;
        GetResponse<Product> response = elasticsearchClient.get(g -> g
                        .index(indexName)
                        .id(productId),
                Product.class
        );

        if (response.found()) {
            product = response.source();
            System.out.println("Product name " + product.getName());
        } else {
            System.out.println("Product not found");
        }

        return product;
    }

    public String deleteDocumentById(String productId) throws IOException {

        DeleteRequest request = DeleteRequest.of(d -> d.index(indexName).id(productId));

        DeleteResponse deleteResponse = elasticsearchClient.delete(request);
        if (Objects.nonNull(deleteResponse.result()) && !deleteResponse.result().name().equals("NotFound")) {
            return new StringBuilder("Product with id " + deleteResponse.id() + " has been deleted.").toString();
        }
        System.out.println("Product not found");
        return new StringBuilder("Product with id " + deleteResponse.id() + " does not exist.").toString();

    }
    public List<Product> searchAllDocuments() throws IOException {

        SearchRequest searchRequest = SearchRequest.of(s -> s.index(indexName));
        SearchResponse searchResponse = elasticsearchClient.search(searchRequest, Product.class);
        List<Hit> hits = searchResponse.hits().hits();
        List<Product> products = new ArrayList<>();
        for (Hit object : hits) {

            System.out.print(((Product) object.source()));
            products.add((Product) object.source());

        }
        return products;
    }

    public List<Product> searching() throws IOException{
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices(indexName);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        QueryBuilder cluase0 = QueryBuilders.multiMatchQuery(queryString, 
                "name",
                  "id",
                  "description",
                  "price");
        MultiMatchQueryBuilder multiMatchQueryBuilder1 = new MultiMatchQueryBuilder(queryString, "firstName", "lastName",
                  "password", "emailId", "userId", "mobileNumber");
            multiMatchQueryBuilder1.operator(Operator.AND);
            searchSourceBuilder.query(multiMatchQueryBuilder1);
         
    }
}

修正后的实现代码

1. 修改Controller接口,接收搜索关键词

将/searching接口改为接收查询参数,支持动态传入搜索关键词:

@GetMapping("/searching")
public ResponseEntity<Object> searching(@RequestParam String keyword) throws IOException{
     List<Product> products = elasticSearchQuery.searchByKeyword(keyword);
     return new ResponseEntity<>(products,HttpStatus.OK);
}

2. 重构ElasticSearchQuery中的搜索方法

你当前混合使用了旧版Elasticsearch High Level Client API与新版co.elastic.clients客户端,需统一使用新版DSL构建查询,避免兼容性问题。替换原searching方法为以下实现:

public List<Product> searchByKeyword(String keyword) throws IOException {
    // 构建与Kibana查询完全对应的multi_match查询
    SearchResponse<Product> response = elasticsearchClient.search(s -> s
            .index(indexName)
            .query(q -> q
                    .multiMatch(m -> m
                            .query(keyword)
                            .fields("description", "name", "id", "price")
                    )
            ), Product.class);

    List<Hit<Product>> hits = response.hits().hits();
    List<Product> products = new ArrayList<>();
    for (Hit<Product> hit : hits) {
        products.add(hit.source());
    }
    return products;
}

3. 清理冗余代码

删除ElasticSearchQuery中未使用的旧API导入(如SearchSourceBuilder、QueryBuilders等)及无效的原searching方法,减少代码冗余。


内容的提问来源于stack exchange,提问作者Ali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 05:00:51