This is the article on the 11th day of Elastic Stack (Elasticsearch) Advent Calendar 2019.
By using "Java High Level REST Client", you can access Elasticsearch via http from Java application.
Previously "TransportClient" was used but is obsolete in 8.0 For, "Java High Level REST Client Tips" or "[Java Low Level REST Client Tips]" Client](https://www.elastic.co/guide/en/elasticsearch/client/java-rest/master/java-rest-low.html) "is recommended.
This time, I will introduce a usage example focusing on search (Search API).
Example) Elasticsearch(7.0) Java High Level REST(7.0) → OK Elasticsearch(7.0) Java High Level REST(6.8) → NG
Elasticsearch environment → ElasticCloud Java8(JDK1.8.0)
PUT /qiita
{
"mappings": {
"properties": {
"user": { "type": "keyword" },
"post_date": { "type": "date" },
"active": { "type": "boolean" },
"message": { "type": "text" }
}
}
}
POST qiita/_doc
{
"user" : "qiita",
"post_date" : "2019-12-11T00:10:30Z",
"active":"false",
"message" : "trying out High Level REST Client"
}
GET qiita/_search
...
{
"_index" : "qiita",
"_type" : "_doc",
"_id" : "yjDo5m4Bj4TzcUq3pmoX",
"_score" : 1.0,
"_source" : {
"user" : "qiita",
"post_date" : "2019-12-11T00:10:30Z",
"active" : "false",
"message" : "trying out High Level REST Client"
}
}
...
pon.xml
<dependencies>
...
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.5.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>7.5.0</version>
</dependency>
...
</dependencies>
Basically, in the example of Initialization no problem
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost", 9200, "http"),
new HttpHost("localhost", 9201, "http")));
client.close();
If you have introduced an authentication function such as Elastic Cloud, you need to make the following settings.
String username = "elastic";
String password = "pass";
String host = "host";
int port = 9243;
int nextPort = 9244;
String protocol = "https";
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(
AuthScope.ANY,
new UsernamePasswordCredentials(username, password));
RestClientBuilder client = RestClient.builder(
new HttpHost(host, port, protocol),
new HttpHost(host, nextPort, protocol))
.setHttpClientConfigCallback((h) -> h.setDefaultCredentialsProvider(credentialsProvider));
RestHighLevelClient client = new RestHighLevelClient(client);
client.close();
You can get something similar to "GET qiita / _search" by using the client you created earlier.
try (RestHighLevelClient client = new RestHighLevelClient(client)) {
SearchSourceBuilder searchBuilder = SearchSourceBuilder.searchSource();
// quite*You can specify a wildcard like
SearchRequest request = new SearchRequest("qiita").source(searchBuilder);
//Data acquisition
SearchHits hits = client.search(request, RequestOptions.DEFAULT).getHits();
for(SearchHit hit : hits) {
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
//Set the value for each record
String user = (String) sourceAsMap.get("user");
String post_date = (String) sourceAsMap.get("post_date");
String message = (String) sourceAsMap.get("message");
System.out.println(String.format("user:%s data:%s message:%s",user , post_date, message));
}
}catch (IOException io) {}
Reference: Search API
Set to "Search Source Builder" The default size is only 10 items
// default 10
SearchSourceBuilder searchBuilder = SearchSourceBuilder.searchSource();
searchBuilder.size(100);
Set to "Search Source Builder" Switch between ASC and DESC with Sort Order
SearchSourceBuilder searchBuilder = SearchSourceBuilder.searchSource();
searchBuilder.sort(new FieldSortBuilder("_id").order(SortOrder.DESC));
Building Queries is all about Here are some simple ones that can be used (not all have been tried) Basically, set to "SearchSourceBuilder"
Obtained from "2019-12-12T00: 10: 30" to "2019-12-13T00: 10: 31" in Japan time
SearchSourceBuilder searchBuilder = SearchSourceBuilder.searchSource();
QueryBuilder query = QueryBuilders
.rangeQuery("post_date")
.from("2019-12-12T00:10:30")
.to("2019-12-13T00:10:31")
.timeZone("+09:00");
searchBuilder.query(query);
It is necessary to be careful if you specify as follows Get from "2019-12-09T 00: 00: 00.000" to "2019-12-13T 23: 59: 59.999"
QueryBuilder query = QueryBuilders
.rangeQuery("post_date")
.from("2019-12-12")
.to("2019-12-13")
.timeZone("+09:00");
searchBuilder.query(query);
To get the data for 12 days only, it will be as follows
"Include Lower" to include from: true "Include Upper" to include to: true
QueryBuilder query = QueryBuilders
.rangeQuery("post_date")
.from("2019-12-12")
.to("2019-12-13")
.includeLower(true)
.includeUpper(false)
.timeZone("+09:00");
searchBuilder.query(query);
Match Query The query for full-text search is below
SearchSourceBuilder searchBuilder = SearchSourceBuilder.searchSource();
QueryBuilder query = QueryBuilders.matchQuery("message", "REST Level ");
QueryBuilder query = QueryBuilders.matchQuery("message", "Level REST");
QueryBuilder query = QueryBuilders.matchPhraseQuery("message", "REST Level");
//Since it is a phrase search, 0 acquisitions
QueryBuilder query = QueryBuilders.matchPhraseQuery("message", "Level REST");
searchBuilder.query(query);
Term Query The Term query that is searched by exact match is as follows
QueryBuilder query = QueryBuilders.termQuery("user", "qiita");
Bool Query(AND OR NOT)
Elastic | Elastic SQL | Description |
---|---|---|
must | AND | |
filter | AND | Ignore the score |
should | OR | |
mustnot | NOT |
AND Either "must" or "filter" is acceptable
An example of "filter" looks like this
SearchSourceBuilder searchBuilder = SearchSourceBuilder.searchSource();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
QueryBuilder query1 = QueryBuilders.matchQuery("message", "JAVA");
QueryBuilder query2 = QueryBuilders.matchQuery("message", "REST");
boolQuery.filter(query1);
boolQuery.filter(query2);
searchBuilder.query(boolQuery);
OR
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
QueryBuilder query1 = QueryBuilders.matchQuery("message", "JAVA");
QueryBuilder query2 = QueryBuilders.matchQuery("message", "REST");
boolQuery.should(query1);
boolQuery.should(query2);
NOT
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
QueryBuilder query = QueryBuilders.termQuery("user", "qiita");
boolQuery.mustNot(query);
You can also get it in JSON format as shown below. Search Template API
SearchTemplateRequest request = new SearchTemplateRequest();
request.setRequest(new SearchRequest("qiita"));
request.setScriptType(ScriptType.INLINE);
request.setScript(
"{" +
" \"query\": { \"match\" : { \"{{field}}\" : \"{{value}}\" } }," +
" \"size\" : \"{{size}}\"" +
"}");
Map<String, Object> scriptParams = new HashMap<>();
scriptParams.put("field", "message");
scriptParams.put("value", "REST");
scriptParams.put("size", 5);
request.setScriptParams(scriptParams);
SearchTemplateResponse response = client.searchTemplate(request, RequestOptions.DEFAULT);
SearchResponse searchResponse = response.getResponse();
SearchHit[] results = searchResponse.getHits().getHits();
Frozen indices It can be used from "Java High Level REST Client" of 6.8.1 Note that it is not reflected when "Frozen indices" is implemented in Elastic saerch.
How to Search Freeze Index using Java High Level REST Client
SearchRequest request = new SearchRequest("qiita").source(searchBuilder);
request.indicesOptions(IndicesOptions.fromOptions(
true,
true,
true,
false,
request.indicesOptions().allowAliasesToMultipleIndices(),
request.indicesOptions().forbidClosedIndices(),
request.indicesOptions().ignoreAliases(),
true //← Set whether frozen index can be searched here true:Searchable
));
There are few Japanese articles on "Java High Level REST Client", and I often read English and Chinese articles. Although it is mostly written in the document, after adding new features, it seems that "Java High Level REST Client" does not support it, so you may have to read the source and release notes.
Tomorrow is @ NAO_MK2.
Recommended Posts