使用Jest查詢Elasticsearch資料
不得不說,使用Elasticsearch的官方客戶端在多個版本的時候很容易出現一些意想不到的問題,然而通過RESTful的方式可以儘可能的相容多個版本的情況。
下面我們通過Jest對Elasticsearch進行操作,這裡使用的Jest版本是6.3.1
,而Elasticsearch版本是6.3.1
。對應的依賴可以ofollow,noindex" target="_blank">訪問
進行下載。
下面我們匯入常用的包:
import java.util.*; import java.io.IOException; import com.google.gson.*; import io.searchbox.client.*; import io.searchbox.core.*; import io.searchbox.core.SearchResult.Hit; import io.searchbox.client.config.*;
接著我們定義1個客戶端類,用於連線對應的客戶端連線:
class ESClient { private static final String ES_HOST = "http://127.0.0.1"; private static final int ES_HTTP_PORT = 9200; private static JestClient client; private static JestClient build(){ JestClientFactory factory = new JestClientFactory(); factory.setHttpClientConfig(new HttpClientConfig.Builder(ES_HOST+":"+ES_HTTP_PORT) .multiThreaded(true) //設定為多執行緒 .defaultMaxTotalConnectionPerRoute(2) .maxTotalConnection(2) //最大連線數 .connTimeout(10000)//設定連線超時 .readTimeout(10000) //設定讀取超時 .gson(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create()) //設定日期的格式 .build()); client = factory.getObject(); return client; } public static synchronized JestClient getClient(){ if(client==null){ client = build(); } return client; } }
這裡我們通過JestClientFactory
的客戶端工廠類的getObject
方法得到對應的物件,並將其返回。
之後我們的呼叫的程式碼:
public class demo { public static void main(String[] args){ JestClient client = new ESClient().getClient(); //構建JSON字串 HashMap<String, Object> query_args = new HashMap<>(); HashMap<String, Object> match = new HashMap<>(); HashMap<String, Object> match_all = new HashMap<>(); match.put("match_all", match_all); query_args.put("query", match); GsonBuilder gsonBuilder = new GsonBuilder(); String query = gsonBuilder.serializeNulls().create().toJson(query_args); //進行RESTful查詢 Search.Builder searchBuilder = new Search.Builder(query).addIndex("demo").addType("person"); try{ SearchResult result = client.execute(searchBuilder.build()); List<Hit<JsonObject, Void>> hits = result.getHits(JsonObject.class); for(Hit<JsonObject, Void> hit: hits){ JsonObject source = hit.source; JsonPrimitive username = source.getAsJsonPrimitive("username"); JsonArray tags = source.getAsJsonArray("tags"); System.out.println(username); System.out.println(tags); } } catch (IOException e){ e.printStackTrace(); e.getMessage(); } } }
在這裡,我們通過HashMap組裝JSON物件,並通過之前介紹的Gson對其進行序列化為字串,於是我們得到類似如下的字串:
{"query":{"match_all":{}}}
接著,我們通過Search.Builder
中傳入1個字串,然後通過addIndex
指定我們要查詢的index名稱,還有對應的doc_type
的名稱。當我們執行ESClient客戶端的execute提交後得到查詢的結果。
而對應的結果類似如下組成的陣列:
{"username":"王五","gender":"男","age":"21","region":"杭州","tags":["吃貨","技術大牛"],"es_metadata_id":"1g3l82UB8TY7aIKswO1s"}
此時,我們通過搜尋結果例項的getHits方法獲取到對應的查詢命中結果。在這裡,我們在getHits方法中傳入Gson中的JsonObject類。
最後,我們進行遍歷,對於基礎資料型別,我們需要設定其為JsonPrimitive
型別,而對於陣列則設定為JsonArray
,同理物件或雜湊表為JsonObject
。這樣我們就得到了對應的Java物件,進行組合並序列化後就可以返回到前端。
在這裡,如果要獲取記錄的總條數,可以通過如下的2種方法來獲取,首先最簡單的方法是:
long total = result.getTotal();
我們直接調用搜索結果的getTotal
方法即可。而第2種方法需要自行對JSON物件進行解析後才可以獲取:
JsonObject hits = result.getJsonObject().getAsJsonObject("hits"); int total = hits.get("total").getAsInt();
同樣的,我們還有最大分數的獲取,可以通過類似的方法來獲得:
float score = result.getMaxScore();
下面我們進行手動解析的過程如下:
JsonObject hits = result.getJsonObject().getAsJsonObject("hits"); if(hits!=null){ JsonArray response = hits.getAsJsonArray("hits"); for(JsonElement resp: response){ JsonObject source = new Gson().fromJson(resp, JsonObject.class).getAsJsonObject("_source"); JsonPrimitive username = source.getAsJsonPrimitive("username"); JsonArray tags = source.getAsJsonArray("tags"); System.out.println(username); System.out.println(tags); } }
可以看到這種方法,相比第1種方法需要編寫更多的程式碼,反而顯得不夠簡潔,不過對於理解其過程很有幫助。