jest客户端连接elasticsearch

Scroll Down

1.介绍

Jest是一个java http rest ES客户端。
ES官方有三种客户端:java api、high level client、low level client
java api在ES近几个大版本中逐渐被官方淘汰,而剩余两种客户端需要手动拼接和解析json,不太方便使用。相较于官方rest客户端,jest的api操作方式不用手动拼接json,易用性更好。

jest官方文档:https://github.com/searchbox-io/Jest/tree/master/jest

2.maven依赖

<dependency>
  <groupId>io.searchbox</groupId>
  <artifactId>jest</artifactId>
  <version>5.3.3</version>
</dependency>

3.使用

3.1.创建client

3.1.1.普通client

// Construct a new Jest client according to configuration via factory
 JestClientFactory factory = new JestClientFactory();
 factory.setHttpClientConfig(new HttpClientConfig
                        .Builder("http://localhost:9200")
                        .multiThreaded(true)
			//Per default this implementation will create no more than 2 concurrent connections per given route
			.defaultMaxTotalConnectionPerRoute(<YOUR_DESIRED_LEVEL_OF_CONCURRENCY_PER_ROUTE>)
			// and no more 20 connections in total
			.maxTotalConnection(<YOUR_DESIRED_LEVEL_OF_CONCURRENCY_TOTAL>)
                        .build());
 JestClient client = factory.getObject();
  • JestClient可以复用,无需每次请求都创建。

3.1.2.集群节点发现

//enable host discovery
 JestClientFactory factory = new JestClientFactory();
 factory.setHttpClientConfig(new HttpClientConfig.Builder(Arrays.asList("http://192.168.0.88:9200", "http://192.168.0.172:9200"))
    //开启节点发现
    .discoveryEnabled(true)
    //节点发现轮询时间
    .discoveryFrequency(1l, TimeUnit.MINUTES)
    //节点过滤
    .discoveryFilter("type:arbitrary")
    .build()
 );

3.1.3.http/ssl连接

// trust ALL certificates
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
    public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
        return true;
    }
}).build();

// skip hostname checks
HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;

SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
SchemeIOSessionStrategy httpsIOSessionStrategy = new SSLIOSessionStrategy(sslContext, hostnameVerifier);

JestClientFactory factory = new JestClientFactory();
factory.setHttpClientConfig(new HttpClientConfig.Builder("https://localhost:9200")
                .defaultSchemeForDiscoveredNodes("https") // required, otherwise uses http
                .sslSocketFactory(sslSocketFactory) // this only affects sync calls
                .httpsIOSessionStrategy(httpsIOSessionStrategy) // this only affects async calls
                .build()
);

3.1.4.用户认证

JestClientFactory factory = new JestClientFactory();
factory.setHttpClientConfig(
    new HttpClientConfig.Builder("http://localhost:9200")
        .defaultCredentials("global_user", "global_password")
        .build()
);

3.1.5.多节点分别进行用户认证

BasicCredentialsProvider customCredentialsProvider = new BasicCredentialsProvider();
customCredentialsProvider.setCredentials(
        new AuthScope("192.168.0.88", 9200),
        new UsernamePasswordCredentials("eu_user", "123")
);
customCredentialsProvider.setCredentials(
        new AuthScope("192.168.0.172", 9200),
        new UsernamePasswordCredentials("us_user", "456")
);

JestClientFactory factory = new JestClientFactory();
factory.setHttpClientConfig(
    new HttpClientConfig.Builder(Arrays.asList("http://192.168.0.88:9200", "http://192.168.0.172:9200"))
        .credentialsProvider(customCredentialsProvider)
        .build()
);

3.1.6.查看节点信息(包含ES版本号)

NodesInfo nodesInfo = new NodesInfo.Builder().build();
client.execute(nodesInfo);

3.2.创建index

3.2.1.简单创建index

client.execute(new CreateIndex.Builder("articles").build());

3.2.2.使用json形式设置索引settings

String settings = "\"settings\" : {\n" +
                "        \"number_of_shards\" : 5,\n" +
                "        \"number_of_replicas\" : 1\n" +
                "    }\n";

client.execute(new CreateIndex.Builder("articles").settings(Settings.builder().loadFromSource(settings).build().getAsMap()).build());

3.2.3.使用SettingsBuilder设置索引settings

SettingsBuilder为ES自带的api。

import org.elasticsearch.common.settings.Settings;


Settings.Builder settingsBuilder = Settings.builder();
settingsBuilder.put("number_of_shards",5);
settingsBuilder.put("number_of_replicas",1);

client.execute(new CreateIndex.Builder("articles").settings(settingsBuilder.build().getAsMap()).build());

3.2.4.获取所有索引

Cat cat = new Cat.IndicesBuilder().build();
client.execute(cat);

3.3.创建索引mapping

3.3.1.使用json形式创建mapping

PutMapping putMapping = new PutMapping.Builder(
        "my_index",
        "my_type",
        "{ \"my_type\" : { \"properties\" : { \"message\" : {\"type\" : \"string\", \"store\" : \"yes\"} } } }"
).build();
client.execute(putMapping);

3.3.2.使用DocumentMapper.Builder创建mapping

DocumentMapper.Builder为ES自带api。

import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.core.StringFieldMapper;
import org.elasticsearch.index.mapper.object.RootObjectMapper;

RootObjectMapper.Builder rootObjectMapperBuilder = new RootObjectMapper.Builder("my_mapping_name").add(
        new StringFieldMapper.Builder("message").store(true)
);
DocumentMapper documentMapper = new DocumentMapper.Builder("my_index", null, rootObjectMapperBuilder).build(null);
String expectedMappingSource = documentMapper.mappingSource().toString();
PutMapping putMapping = new PutMapping.Builder(
        "my_index",
        "my_type",
        expectedMappingSource
).build();
client.execute(putMapping);

3.4.写documents

3.4.1.使用json形式写数据

String source = "{\"user\":\"kimchy\"}";

3.4.2.使用JSONBuilder写数据

JSONBuilder为ES自带api。

String source = jsonBuilder()
.startObject()
.field("user", "kimchy")
.field("postDate", "date")
.field("message", "trying out Elastic Search")
.endObject().string();

3.4.3.使用map写数据

Map<String, String> source = new LinkedHashMap<String,String>();
source.put("user", "kimchy");

3.4.4.使用bean写数据

Article source = new Article();
source.setAuthor("John Ronald Reuel Tolkien");
source.setContent("The Lord of the Rings is an epic high fantasy novel");

Index index = new Index.Builder(source).index("twitter").type("tweet").build();
client.execute(index);

使用@JestId注解可以指定bean的id,如果值是null,会注入ES内部生成的_id。

class Article {

@JestId
private String documentId;

}

使用@JestVersion注解可以指定bean的documents版本(_version)

class Article {

@JestId
private String documentId;

@JestVersion
private Long documentVersion;

}

3.5.搜索documents

3.5.1.使用json搜索数据

String query = "{\n" +
            "    \"query\": {\n" +
            "        \"filtered\" : {\n" +
            "            \"query\" : {\n" +
            "                \"query_string\" : {\n" +
            "                    \"query\" : \"test\"\n" +
            "                }\n" +
            "            },\n" +
            "            \"filter\" : {\n" +
            "                \"term\" : { \"user\" : \"kimchy\" }\n" +
            "            }\n" +
            "        }\n" +
            "    }\n" +
            "}";

Search search = new Search.Builder(query)
                // multiple index or types can be added.
                .addIndex("twitter")
                .addType("tweet")
                .build();

SearchResult result = client.execute(search);

3.5.2.使用模板搜索数据

String query = "{\n" +
            "    \"id\": \"myTemplateId\"," +
            "    \"params\": {\n" +
            "        \"query_string\" : \"search for this\"" +
            "    }\n" +
            "}";

Search search = new Search.TemplateBuilder(query)
                // multiple index or types can be added.
                .addIndex("twitter")
                .addType("tweet")
                .build();

SearchResult result = client.execute(search);

3.5.3.使用SearchSourceBuilder搜索数据

SearchSourceBuilder为ES自带api。

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchQuery("user", "kimchy"));

Search search = new Search.Builder(searchSourceBuilder.toString())
                                // multiple index or types can be added.
                                .addIndex("twitter")
                                .addType("tweet")
                                .build();

SearchResult result = client.execute(search);

3.5.4.结果可以直接转为bean

SearchResult result = client.execute(search);
List<SearchResult.Hit<Article, Void>> hits = result.getHits(Article.class);
// or
List<Article> articles = result.getSourceAsObjectList(Article.class);

3.6.获取documents

Get get = new Get.Builder("twitter", "1").type("tweet").build();
JestResult result = client.execute(get);
Article article = result.getSourceAsObject(Article.class);

3.7.更新documents

String script = "{\n" +
                "    \"script\" : \"ctx._source.tags += tag\",\n" +
                "    \"params\" : {\n" +
                "        \"tag\" : \"blue\"\n" +
                "    }\n" +
                "}";

client.execute(new Update.Builder(script).index("twitter").type("tweet").id("1").build());

3.8.删除document

client.execute(new Delete.Builder("1")
                .index("twitter")
                .type("tweet")
                .build());

3.9.bulk api批量操作

3.9.1.单条数据

Bulk bulk = new Bulk.Builder()
    .defaultIndex("twitter")
    .defaultType("tweet")
    .addAction(new Index.Builder(article1).build())
    .addAction(new Index.Builder(article2).build())
    .addAction(new Delete.Builder("1").index("twitter").type("tweet").build())
    .build();

client.execute(bulk);

3.9.2.多条数据

String article1 = "tweet1";
String article2 = "tweet2";

Bulk bulk = new Bulk.Builder()
                .defaultIndex("twitter")
                .defaultType("tweet")
                .addAction(Arrays.asList(
                    new Index.Builder(article1).build(),
                    new Index.Builder(article2).build()))
                .build();

client.execute(bulk);

3.10.设置请求参数

ES可以将路由、版本、操作类型等属性通过请求参数的方式设置,如设置refresh属性,如要设置枚举中没有的属性,可以直接填字符串。

Index index = new Index.Builder("{\"user\":\"kimchy\"}")
    .index("cvbank")
    .type("candidate")
    .id("1")
    .setParameter(Parameters.REFRESH, true),
    .build();
client.execute(index);

3.11.jest支持异步操作

client.executeAsync(action,new JestResultHandler<JestResult>() {
    @Override
    public void completed(JestResult result) {
        ... do process result ....
    }
    @Override
    public void failed(Exception ex) {
       ... catch exception ...
    }
});