MacOS el capitan に
作成した
実装した
前提
以下、
OS
sw_vers ---------------------------- ProductName: Mac OS X ProductVersion: 10.12.3 BuildVersion: 16D32 ----------------------------
Java
java -version ---------------------------- java version "1.8.0_45" Java(TM) SE Runtime Environment (build 1.8.0_45-b14) Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode) ----------------------------
Elasticsearch
elasticsearch -version ---------------------------- Version: 5.2.2, Build: f9d9b74/2017-02-24T17:26:45.835Z, JVM: 1.8.0_45 ----------------------------
Elasticsearch Java Dependency
<!-- https://mvnrepository.com/artifact/org.elasticsearch/elasticsearch --> <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>5.2.2</version> </dependency> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>transport</artifactId> <version>5.2.2</version> </dependency>
ページングで 必要な 処理
基本的な
Limit、
Offset を 指定して、 ページング表示件数分データを 取得する 処理 Count クエリで、
データ全件の 件数のみ 取得する 処理
あとは、
キーワードが
ElasticSearch の クエリの 記述
1. ElasticSearch での Limit Offset 指定
第4回 Elasticsearch 入門 検索の
でlimit
とoffset
と
json形式で
curl -XPOST 'localhost:9200/festival/_search?pretty' -d ' { "query": { "match": { "name" : "ROCK" } }, "from": 0, "size": 20 }' -------------------------- { "took" : 215, "timed_out" : false, "_shards" : { "total" : 5, "successful" : 5, "failed" : 0 }, "hits" : { "total" : 34, "max_score" : 3.1631145, "hits" : [ ...... ] } }
2. ElasticSearch で 件数を 取得する
elasticsearchと
件数取得に"size" : 0
と
[1] size 1以上を
curl -XPOST 'localhost:9200/festival/_search?pretty' -d ' { "query": { "match": { "name" : "ROCK" } }, "from": 0, "size": 0 }' ------------------------------------------------- { "took" : 34, "timed_out" : false, "_shards" : { "total" : 5, "successful" : 5, "failed" : 0 }, "hits" : { "total" : 34, "max_score" : 0.0, "hits" : [ ] } }
3. ElasticSearch で 条件指定なしで データを 取得する
elasticsearchとmatch_all
で
curl -XPOST 'localhost:9200/festival/_search?pretty' -d ' { "query": { "match_all": {} }, "from": 0, "size": 20 }' -------------------------------------------------- { "took" : 274, "timed_out" : false, "_shards" : { "total" : 5, "successful" : 5, "failed" : 0 }, "hits" : { "total" : 547, "max_score" : 1.0, "hits" : [ ...... ] } } }
Java Client の 実装
TransportClientを 使った 検索クラス
実装した
import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.io.Resources; import org.apache.commons.lang3.StringUtils; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.transport.TransportClient; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.InetSocketTransportAddress; import org.elasticsearch.script.ScriptType; import org.elasticsearch.script.mustache.SearchTemplateRequestBuilder; import org.elasticsearch.search.SearchHit; import org.elasticsearch.transport.client.PreBuiltTransportClient; import xyz.monotalk.festivals4partypeople.models.elasticsearch.dto.Festival; import java.io.IOException; import java.net.InetAddress; import java.net.URL; import java.net.UnknownHostException; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; /** * FestivalIndex */ public class FestivalIndex { /** * findByKeywordWithPaging * * @param keyword * @param from * @param size * @return */ public List<Festival> findByKeywordWithPaging(String keyword, int from, int size) { // on startup TransportClient client = getTransportClient(); String scripts = StringUtils.isEmpty(keyword) ? getResourceAsString("scripts/Festival_findAllWithPaging.json") : getResourceAsString("scripts/Festival_findByKeywordWithPaging.json"); SearchRequest searchRequest = new SearchRequest(); searchRequest.indices("festival"); Map<String, Object> template_params = new HashMap<>(); if (!StringUtils.isEmpty(keyword)) { template_params.put("keyword", keyword); } template_params.put("from", from); template_params.put("size", size); SearchResponse sr = new SearchTemplateRequestBuilder(client) .setScript(scripts) .setScriptType(ScriptType.INLINE) .setScriptParams(template_params) .setRequest(searchRequest) .get() .getResponse(); SearchHit[] results = sr.getHits().getHits(); List<Festival> festivals = new ArrayList<>(); for (SearchHit hit : results) { String sourceAsString = hit.getSourceAsString(); if (sourceAsString != null) { ObjectMapper mapper = new ObjectMapper(); Festival fes = null; try { fes = mapper.readValue(sourceAsString, Festival.class); } catch (IOException e) { e.printStackTrace(); } festivals.add(fes); } } client.close(); return festivals; } /** * getRecordCountByKeyword * * @param keyword * @return */ public long getRecordCountByKeyword(String keyword) { TransportClient client = getTransportClient(); String scripts = StringUtils.isEmpty(keyword) ? getResourceAsString("scripts/Festival_getAllRecordCount.json") : getResourceAsString("scripts/Festival_getRecordCountByKeyword.json"); SearchRequest searchRequest = new SearchRequest(); searchRequest.indices("festival"); Map<String, Object> template_params = new HashMap<>(); if (!StringUtils.isEmpty(keyword)) { template_params.put("keyword", keyword); } SearchResponse sr = new SearchTemplateRequestBuilder(client) .setScript(scripts) .setScriptType(ScriptType.INLINE) .setScriptParams(template_params) .setRequest(searchRequest) .get() .getResponse(); long hits = sr.getHits().getTotalHits(); client.close(); return hits; } /** * 2度呼び出されるため、メソッド化 * getTransportClient * * @return */ private TransportClient getTransportClient() { TransportClient client = null; try { client = new PreBuiltTransportClient(Settings.builder() .put("cluster.name", "elasticsearch_clustername").put("client.transport.sniff", false) .put("node.name", "JlcSImk") .put("client.transport.ping_timeout", 20, TimeUnit.SECONDS).build()) .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("10.0.1.4"), 9300)); } catch (UnknownHostException e) { e.printStackTrace(); } return client; } /** * guava の Resourcesクラスを使って、src/main/resources配下のファイルをStringで取得 * getResourceAsString * * @param resourceName * @return */ private String getResourceAsString(String resourceName) { String scripts = null; URL url = Resources.getResource(resourceName); try { scripts = Resources.toString(url, Charset.forName("utf-8")); } catch (IOException e) { e.printStackTrace(); } return scripts; } }
- findByKeywordWithPagingの
説明
キーワードを
キーワードが
[2] 何かもっと
現状、
SearchRequest searchRequest = new SearchRequest(); searchRequest.indices("festival");
指定しないと
- getRecordCountByKeywordの
説明
キーワードを
キーワードが
トータル件数は、getHits().getTotalHits();
で
作成した スクリプトファイル
src/main/resources/scripts/Festival_findAllWithPaging.json
{ "query": { "match_all": {} }, "from": "{{from}}", "size": "{{size}}" }
src/main/resources/scripts/Festival_findByKeywordWithPaging.json
{ "query": { "match": { "name": "{{keyword}}" } }, "from": "{{from}}", "size": "{{size}}" }
src/main/resources/scripts/Festival_getAllRecordCount.json
{ "query": { "match_all": {} }, "size": 0 }
src/main/resources/scripts/Festival_getRecordCountByKeyword.json
{ "query": { "match": { "name": "{{keyword}}" } }, "size": 0 }
まとめ
SearchTemplateRequestBuilder
に
結構冗長にSearchTemplateRequestBuilder
の
一旦
QueryBuilders
を
Count API はCountResponse
を
Java API changes | Elasticsearch Reference [5.2] | Elastic
に
client.prepareSearch(indices).setSource(new SearchSourceBuilder().size(0).query(query)).get();
一旦、SearchTemplateRequestBuilder
ゴリ押しで
コメント