从 Java API Client in Spring Boot REST API 返回整个 Elasticsearch 响应(作为 SearchResponse)

returning the entire Elasticsearch response (as SearchResponse) from Java API Client in Spring Boot REST API

我正在学习 Elasticsearch 和 Java 客户端 API(目前仅关注文档),它运行良好,但我想知道是否可以 return查询返回的整个搜索响应?到目前为止,我只从包含三个 class 变量的命中中取回“_source”部分。这很好,但我想尝试使用整个响应,就像我在 Kibana 控制台中看到的那样。这是我的 classes 和 REST 点:

客户端配置:

@Configuration
public class ClientConf {
    
    RestClient restClient = RestClient.builder(new HttpHost("localhost", 9200)).build();
    ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
    ElasticsearchClient client = new ElasticsearchClient(transport);

}

发生查询的class:

@Component
public class ElasticSearcher {
    
    @Autowired
    ClientConf conf;

    public List<Product> searchByType(String type) throws Exception{
        List<Product> returnProduct = new ArrayList<Product>();
        
        //searches EXACT term
        SearchResponse<Product> search = conf.client.search(s -> s
                .index("test")
                .query(q -> q
                    .term(t -> t
                        .field("type")
                        .value(v -> v.stringValue(type))
                    )),
                Product.class);
        
        List<Hit<Product>> hits = search.hits().hits();
         
        
        for (Hit<Product> hit: hits) {
            returnProduct.add(hit.source());
        }
        
        return returnProduct;

    }
    
    public void indexProduct(String type, String name, double price) throws ElasticsearchException, IOException {
        Product product = new Product(type, name, price);
        
// I was just trying both variants here
//      IndexResponse response=conf.client.index(i->i
//              .index("test")
//              .document(product)
//              );
        
        IndexRequest<Product> request = IndexRequest.of(i -> i
                .index("test")
                .document(product)
            );
        
        IndexResponse response = conf.client.index(request);
    }
    
    public Product getById(String id) throws ElasticsearchException, IOException {
        
        Product product=null;
        
        GetResponse<Product> response = conf.client.get(g -> g
                .index("test") 
                .id(id),
                Product.class      
            );
        
        if (response.found()) {
            product = response.source();
        } 
        
        return product;
    }
    
//this is the one I'm trying to return entire responses with:
    public SearchResponse matchNameSearch(String text) throws ElasticsearchException, IOException{
                
        SearchResponse response = conf.client.search(s -> s
                .index("test") 
                .query(q -> q      
                    .match(t -> t   
                        .field("name")  
                        .query(text)
                    )
                ),
                Product.class      
            );

        return response;
    }

    
}

编辑:如果我调用 matchNameSearch(我使用 Postman 进行测试),它 return 是一个空对象。我假设 returning response,这是一个 SearchResponse class 会给我完整的回复吗?

我正在使用的对象class:

//I have lombok
@Data
public class Product {
    
    private String type;
    private String name;
    private double price;
    
    public Product() {
        
    }
    
    public Product(String type, String name, double price) {
        this.type=type;
        this.name=name;
        this.price=price;
    }

}

最后,其余端点:

@RestController
public class SearchController {
    
    @Autowired
    ElasticSearcher searcher;
    
    @GetMapping("/search/{type}")
    public List<Product> searchByType(@PathVariable("type") String type) throws Exception {
        return searcher.searchByType(type);
    }
    
    @PostMapping("/index/{type}/{name}/{price}")
    public void indexProduct(@PathVariable("type") String type,
                                @PathVariable("name") String name,
                                @PathVariable("price") String price) throws ElasticsearchException, IOException {
        searcher.indexProduct(type, name, Double.parseDouble(price));
    }
    
    @GetMapping("/read/{id}")
    public Product searchById(@PathVariable("id") String id) throws ElasticsearchException, IOException {
        return searcher.getById(id);
    }
    

//this is the one:
    @GetMapping("/match/{text}")
    public SearchResponse matchText(@PathVariable("text") String text) throws ElasticsearchException, IOException{
        return searcher.matchNameSearch(text);
    }

}

也欢迎任何改进代码的指示。我事先不了解(现已弃用的)高休息客户端如何工作,所以我实际上不知道构建此类应用程序的最佳方法是什么。

您可以使用 SearchResponse<> class 得到它,您正在使用 product class 映射搜索响应的 hits 部分JSON api,但它具有您在 Kibana 上获得的所有元数据(Kibana 还提供搜索 API 的 JSON 输出)。

下面是 SearchResponse class 中的示例字段,您可以注意到它类似于搜索 JSON 输出。

@JsonpDeserializable
public class SearchResponse<TDocument> implements JsonpSerializable {
    private final long took;
    private final boolean timedOut;
    private final ShardStatistics shards;
    private final HitsMetadata<TDocument> hits;
    private final Map<String, Aggregate> aggregations;
    @Nullable
    private final ClusterStatistics clusters;
    private final Map<String, JsonData> fields;
    @Nullable
    private final Double maxScore;
    @Nullable
    private final Long numReducePhases;
    @Nullable
    private final Profile profile;
    @Nullable
    private final String pitId;
    @Nullable
    private final String scrollId;
    private final Map<String, List<Suggestion<TDocument>>> suggest;
    @Nullable
    private final Boolean terminatedEarly;