やったこと
Elasticsearch + docker
- http://tech.innovation.co.jp/2018/08/09/constructing-enviroment-for-Elasticsearch-and-Kibana.html
- https://qiita.com/sugikeitter/items/f3b2c57bf8bbdc47a8bc
上記URLを参考にElasticsearchをdockerで動かす環境を作る。
docker-compose.xml
version: '2' services: elasticsearch: build: elasticsearch volumes: - elasticsearch-data:/usr/share/elasticsearch/data - ./elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.ymlig/elasticsearch.yml ports: - 9200:9200 - 9300:9300 kibana: build: kibana ports: - 5601:5601 volumes: elasticsearch-data: driver: local
elasticsearch/Dockerfile
FROM docker.elastic.co/elasticsearch/elasticsearch:6.6.1 RUN elasticsearch-plugin install analysis-kuromoji
kibana/Dockerfile
FROM docker.elastic.co/kibana/kibana:6.6.1
elasticsearch/config/elasticsearch.yml
cluster.name: docker-cluster
Spring Data Elasticsearch
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.3.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <groupId>kagamihoge</groupId> <artifactId>spring-erasticsearch-sample</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>spring-erasticsearch-sample</name> <url>http://maven.apache.org</url> <properties> <java.version>10</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> </project>
java
package kagamihoge.springerasticsearchsample; import java.net.InetAddress; import java.net.UnknownHostException; import org.elasticsearch.client.Client; import org.elasticsearch.client.transport.TransportClient; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.transport.client.PreBuiltTransportClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories; import kagamihoge.springerasticsearchsample.repository.SampleDataRepository; @SpringBootApplication @EnableElasticsearchRepositories(basePackages = "kagamihoge.springerasticsearchsample.repository") public class App implements CommandLineRunner { public static void main(String[] args) { SpringApplication.run(App.class, args); } @Bean public Client client() throws UnknownHostException { Settings elasticsearchSettings = Settings.builder().put("cluster.name", "docker-cluster").build(); TransportClient client = new PreBuiltTransportClient(elasticsearchSettings); client.addTransportAddress(new TransportAddress(InetAddress.getByName("127.0.0.1"), 9300)); return client; } @Autowired ElasticsearchOperations elasticsearchTemplate; @Autowired SampleDataRepository repository; @Override public void run(String... args) throws Exception { elasticsearchTemplate.createIndex(SampleData.class); SampleData d = new SampleData(); d.id = "id0002"; d.title = "title-bbbb"; repository.save(d); } }
"cluster.name"
にelasticsearch/config/elasticsearch.yml
で指定したのと同じ名前を使用する。hostとportを指定するところでは、hostはともかく、portはデフォルトではelasticsearchが9300で公開するポートを使用する。なのでdocker-compose.xml
で9300をフォワーディングしている。
package kagamihoge.springerasticsearchsample.repository; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; import org.springframework.stereotype.Repository; import kagamihoge.springerasticsearchsample.SampleData; @Repository public interface SampleDataRepository extends ElasticsearchRepository<SampleData, String> { }
repositoryはこんな感じ。spring-data-jpa触った事あればなんとなく分かる。
package kagamihoge.springerasticsearchsample; import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; @Document(indexName = "sample", type = "data") public class SampleData { @Id String id; String title; }
実行結果
これを実行したあとkibanaのdevtoolsで、
GET /sample/data/_search
すると、こんな感じに結果が返ってくる。
{ "took" : 2, "timed_out" : false, "_shards" : { "total" : 5, "successful" : 5, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : 2, "max_score" : 1.0, "hits" : [ { "_index" : "sample", "_type" : "data", "_id" : "id0002", "_score" : 1.0, "_source" : { } }, { "_index" : "sample", "_type" : "data", "_id" : "id0001", "_score" : 1.0, "_source" : { } } ] } }
その他
elasticsearchとspring data elasticsearchの対応バージョン
https://github.com/spring-projects/spring-data-elasticsearch を見ると、両者の対応バージョン表がある。今回使ってみたのは6.6 + 3.1.5なので微妙にマッチしていないのだが、なんか動いている。この表はあくまでもspringのライブラリ対応表ってだけなんだろうか? ただ、ぐぐってみるとバージョン違いで動作しないケースも結構あるようなので、その辺は事前に調べておくのが良い気がする。
はまった点
None of the configured nodes are available
なんかこんな感じのエラーが出て接続できなかった。
Caused by: org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are available: [{#transport#-1}{zRBMC1NWSPeowkxoa2bIpQ}{localhost}{127.0.0.1:9200}] at org.elasticsearch.client.transport.TransportClientNodesService.ensureNodesAreAvailable(TransportClientNodesService.java:349) ~[elasticsearch-6.4.3.jar:6.4.3] at org.elasticsearch.client.transport.TransportClientNodesService.execute(TransportClientNodesService.java:247) ~[elasticsearch-6.4.3.jar:6.4.3] at org.elasticsearch.client.transport.TransportProxyClient.execute(TransportProxyClient.java:60) ~[elasticsearch-6.4.3.jar:6.4.3]
9200はhttpで、TransportClient
で接続する場合は9300(elasticsearchのデフォルト)を使う必要がある。加えて、dockerの場合これをポートフォワーディングしとく必要がある。