2017-07-14 89 views
0

我用Spring開發了一個REST API條目,它在Elasticsearch中進行搜索,現在我想返回ES發現的任何結果作爲響應。我不關心搜索結果,我不知道其中的JSON結構。我只是想把它還給客戶端。如何將Elasticsarch的結果連接到Spring的REST API響應

我希望像這樣的工作:

 
@RequestMapping(value = "/search/{index:.*}", method = RequestMethod.GET) 
public void search(@PathVariable String index, @RequestParam Map allRequestParams, HttpServletResponse response) 
    throws IOException 
{ 
    BoolQueryBuilder query = QueryBuilders.boolQuery(); 
    for (Map.Entry entry : allRequestParams.entrySet()) { 
     query.should(QueryBuilders.fuzzyQuery(entry.getKey(), entry.getValue())); 
    } 

    SearchResponse results = esClient.prepareSearch("nyc_visionzero") 
     .setTypes("logs") 
     .setQuery(query) 
     .execute() 
     .actionGet(); 

    SearchHits hits = results.getHits(); 
    hits.writeTo(response.getOutputStream()); 
} 

但最後一行有一個編譯錯誤,因爲這兩個OutputStreams是不兼容的。所以我的問題是,將Elasticsearch的結果連接到Spring的最簡單方法是什麼?

回答

1

我設法找到解決自己:

@RequestMapping(value = "/search/{index:.*}", method = RequestMethod.GET) 
public void search(@PathVariable String index, @RequestParam Map<String, String> allRequestParams, HttpServletResponse response) 
    throws IOException 
{ 
    BoolQueryBuilder query = QueryBuilders.boolQuery(); 
    for (Map.Entry<String, String> entry : allRequestParams.entrySet()) { 
     query.should(QueryBuilders.fuzzyQuery(entry.getKey(), entry.getValue())); 
    } 

    SearchResponse results = esClient.prepareSearch("nyc_visionzero") 
     .setTypes("logs") 
     .setQuery(query) 
     .execute() 
     .actionGet(); 

    SearchHits hits = results.getHits(); 

    ServletOutputStream os = response.getOutputStream(); 
    XContentBuilder builder = XContentFactory.jsonBuilder(os); 
    results.toXContent(builder, ToXContent.EMPTY_PARAMS); 
    builder.close(); 
    os.close(); 
} 
1

而不是嘗試寫入響應輸出流,您可以更改您的搜索方法的簽名以返回一個字符串,然後直接返回結果作爲有效的JSON。喜歡的東西:

@RequestMapping(value = "/search/{index:.*}", method = RequestMethod.GET) 
public String search(@PathVariable String index, @RequestParam Map allRequestParams, HttpServletResponse response) 
    throws IOException 
{ 
    BoolQueryBuilder query = QueryBuilders.boolQuery(); 
    for (Map.Entry entry : allRequestParams.entrySet()) { 
     query.should(QueryBuilders.fuzzyQuery(entry.getKey(), entry.getValue())); 
    } 

    SearchResponse results = esClient.prepareSearch("nyc_visionzero") 
     .setTypes("logs") 
     .setQuery(query) 
     .execute() 
     .actionGet(); 

    SearchHits hits = results.getHits(); 

    // Replacing hits.writeTo(response.getOutputStream()); below 
    StringBuilder builder = new StringBuilder(); 
    SearchHit[] hitsDatas = hits.hits(); 
    int length = hitsDatas.length; 
    builder.append("["); 
    for (int i = 0; i < length; i++) { 
     if (i == length - 1) { 
      builder.append(hitsDatas[i].getSourceAsString()); 
     } else { 
      builder.append(hitsDatas[i].getSourceAsString()); 
      builder.append(","); 
     } 
    } 
    builder.append("]"); 
    return builder.toString(); 
} 
+0

謝謝,但我已經找到了更好的解決方案,我將在秒後它。 – Mehran

+0

@Mehran,是的,這是一個不錯的。 Upvoted! – alainlompo

-1
@RequestMapping(value = "/search/{index:.*}", method = RequestMethod.GET) 
public ResponseEntity<?> search(@PathVariable String index, @RequestParam Map allRequestParams) 
{ 
BoolQueryBuilder query = QueryBuilders.boolQuery(); 
for (Map.Entry entry : allRequestParams.entrySet()) { 
    query.should(QueryBuilders.fuzzyQuery(entry.getKey(), entry.getValue())); 
} 

SearchResponse results = esClient.prepareSearch("nyc_visionzero") 
    .setTypes("logs") 
    .setQuery(query) 
    .execute() 
    .actionGet(); 

SearchHits hits = results.getHits(); 
return new ResponseEntity<>(hits , HttpStatus.OK); 
} 

與ResponseEntity類,你可以返回任何響應,而無需關心你的結果類型。

+0

謝謝,但它不這樣工作。我認爲它與傑克遜或某事有一些問題,並導致一些運行時錯誤。 – Mehran