Elasticsearch 官方本來是有提供官方的 SDK 可以用來操作 Elasticsearch
不過…官方版的 SDK 在存取 Elasticsearch 時,是把自己當作 Elasticsearch Cluster 的一員來看待
因此會有包括 heartbeat 等行為在 SDK 裡自動發生。
理論上這麼做的好處是,SDK 可以看見整個 Cluster 的狀態,因此可以比較妥善地選擇存取的節點
不過代價就是維持 Elasticsearch 連線所需要的資源更多、連線速度感覺好像變慢
此外,對於跑在 AWS Lambda 的程式來說,有不少潛在的缺點。
在 Elasticsearch 官方的描述 [1] 中,有建議了可以考慮使用 Jest [2],因此就來試試它了。
Maven 設定
Jest 目前的文件,其實有點看不太出來該怎麼依據使用的 Elasticsearch 版本做選擇
我自己環境的 Elasticsearch 是 5.4 版,現在是使用 2.4.0 版的 Jest。
Dependency 設定如下
<dependency> <groupId>io.searchbox</groupId> <artifactId>jest</artifactId> <version>2.4.0</version> </dependency> <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>5.4.3</version> <exclusions> <exclusion> <groupId>org.elasticsearch.plugin</groupId> <artifactId>*</artifactId> </exclusion> </exclusions> </dependency>
其中,這裡有設定了兩個 dependency,一個是 Jest,另一個是 Elasticsearch 原生的 SDK
至於為什麼要這麼做,主要是在於想要存取 Elasticsearch 時,想要使用 SDK 裡提供的 QueryBuilders
這樣程式碼寫起來會比直接寫純文字來得易讀。
建立連線
建立連線的部份,如果想要做些細部的設定,可以從 HttpClientConfig 這個地方著手。
List addressList = new LinkedList<>(); addressList.add("http://xxx.xxx.xxx.xxx:9200"); Gson gson = new Gson(); HttpClientConfig config = new HttpClientConfig.Builder(addressList) .multiThreaded(true) .maxTotalConnection(10) .gson(gson) .build(); JestClientFactory factory = new JestClientFactory(); factory.setHttpClientConfig(config); JestClient client = factory.getObject();
第一行的 addressList 就是存取 Elasticsearch 的路徑,這裡需要是完整的 URL。
另外 Jest 查回來的東西,可以使用 GSON 自動做序列化,因此 Jest 內部需要一個 GSON 的實體
可以自己指定一個自己已經在使用的實體,或者不指定,Jest 也會自己產生一個。
查詢 Elasticsearch
要查詢 Elasticsearch 時,前面有提到了,我想要用 SDK 提供的 QueryBuilders
因此查詢式的組成,這裡會用 SDK 提供的 QueryBuilders 和 SearchSourceBuilder 來建立。
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder() .query(QueryBuilders.termQuery("field", "value")); Search searchQuery = new Search.Builder(sourceBuilder.toString()) .addIndex("myindex") .build(); SearchResult result = client.execute(sourceBuilder.toString());
這裡使用的是 Term Query,查詢的 index 是 myindex。然後搜尋標的是欄位 field 的值是 value 的資料。
取得結果並且序列化
前面也有提到,Jest 預設會使用 GSON 做序列化,因此假設我已經定義了一個 class MyObject 用來表達 Elasticsearch 上的資料
那麼在 Jest 的搜尋結果中,就可以直接指定類別,讓它將查詢結果序列化。
List<MyObject> objects = result.getHits(MyObject.class).stream() .map(obj -> obj.source) .collect(Collectors.toList());
這裡同時使用了 Lambda Expression,只收集查詢結果而略過其他 Elasticsearch 的回覆(例如 score 等等)。
沒有留言:
張貼留言