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

Time:05-07

I'm learning about Elasticsearch and the Java Client API (currently just following the documentation), it works well but I'm wondering if it's possible to return the whole search response from a query back? So far I only get back the "_source" part from the hits containing the three class variables. Which is good but I want to try one with the whole response like I would see in the Kibana console. Here are my classes and REST points:

Client configuration:

@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);

}

The class where the queries take place:

@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;
    }

    
}

Edit: if I call upon matchNameSearch (I test with Postman), it returns an empty object. I assumed by returning response, which is a SearchResponse class would give me the entire response?

the object class I'm using:

//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;
    }

}

Lastly, the rest endpoints:

@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);
    }

}

Any pointers in improving the code is also welcome. I have no prior knowledge to how the (now deprecated) high rest client worked, so I don't actually know what the best way to build this kind of application is.

CodePudding user response:

You can get that using the SearchResponse<> class , You are using the product class to map the hits section of the search response of the JSON api, but it has all the metadata which you get on Kibana(Kibana also provides the JSON output of search API).

Below is the sample fields in the SearchResponse class, and you can notice its similar to Search JSON output.

@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;

  • Related