preface
Previously we mentioned the Rest Api for Elastic Search to manipulate indexes. In fact, the Rest Api of Elastic Search provides all of the operational interfaces. In programming languages, you can use the Rest Api to call all the functions of Elastic Search, but it’s not very convenient and intuitive, so Elastic Search has an Api that can be accessed by many languages. The official programming language interfaces include:
- Java
- JavaScript
- Groovy
- PHP
- .NET
- Perl
- Python
- Ruby
The programming community also provides a number of programming language apis. At present, there are mainly
- B4J
- Clojure
- ColdFusion (CFML)
- Erlang
- Go
- Groovy
- Haskell
- Java
- JavaScript
- kotlin
- Lua
- .NET
- OCaml
- Perl
- PHP
- Python
- R
- Ruby
- Rust
- Scala
- Smalltalk
- Vert.x
We usually develop in Java. So I’m going to talk a little bit about how the Java Api for Elastic Search is used
The preparatory work
To illustrate the capabilities of the Java Api, we have prepared a scenario. Here we assume that we have a set of authors, each with an id, name, gender, age, describing several fields. We need to look up the author by name, age, keywords in the description,
Here, the program is run primarily through JUnit test cases, so JUnit dependencies are introduced first
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
Copy the code
Java Api overview
Elastic Search provides an official Java Api. There are two types of Rest apis: Low Level Rest Api and High Leve Rest Api.
Low-level apis do not mean that they are weaker, but that they are closer to the underlying implementation. The officially provided low-level Api is the first layer of encapsulation of the original Rest Api. It just wraps up the details of the Http call. The program still assembles the query’s conditional string, parses the returned JSON string, and so on. It also deals with HTTP protocol methods, protocols, and other content.
The high-level API is a further encapsulation of the low-level API, which does not care about the interface methods, protocol headers, or the manual combination of call parameter strings, and has some parsing of the returned JSON string. It’s more convenient to use. But the high-level API does not do what all the low-level apis do. So if this is the case, you need to use low-level apis to implement your own functionality.
The third-party Java client is the community-developed Elastic Search client. Officials point to two open source GitHub projects, Flummi and Jest
Java Low Level Rest Api usage guide
The advantage of low-level apis is that they rely on very few other libraries and are fully functional. The disadvantage is that the package is not advanced enough, so it is very cumbersome to use. Let’s take a look at how low-level apis are used.
Introduction of depend on
To use the low-level Api of Elastic Search in the Maven Java project set up earlier, you must first import the low-level Api dependencies. As shown below.
<dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-client</artifactId> The < version > 6.1.1 < / version > < / dependency >Copy the code
Setting up a client
RestClient restClient = RestClient.builder(
new HttpHost("localhost", 9200, "http"),
new HttpHost("localhost", 9201, "http")).build();
Copy the code
The RestClient object’s static method builder(HttpHost… Hosts and Builder () to create a Rest client for Elastic Search. Hosts is a variable parameter that specifies the IP addresses, ports, and protocols of nodes in an Elastic Cluster.
The method call
Once the client is set up, the Rest Api is invoked through two classes of methods. One is synchronous invocation and one is asynchronous invocation.
A synchronous invocation
The main method declarations for synchronous calls are as follows:
public Response performRequest(String method, String endpoint, Header... headers) throws IOException
public Response performRequest(String method, String endpoint, Map<String, String> params, Header... headers) throws IOException
public Response performRequest(String method, String endpoint, Map<String, String> params,
HttpEntity entity, Header... headers) throws IOException
Copy the code
These are three overloaded methods. The parameter method represents Rest Api methods, such as PUT, GET, POST, DELETE, etc. The endpoint of the parameter represents the Rest Api parameter address, starting from the IP :port field of the Rest Api URL. Params are parameters passed as URL parameters; Entity is a parameter passed through the HTTP Body; Headers is a variable argument that can be passed in the corresponding HTTP header information.
For example, if I want to view information about an index author_test, we can get it with the following code
Response response = restClient.performRequest("GET"."/author_test");
Copy the code
For example, if we want to check the document information containing software in the DES field of an index author_test, we can use the following code to obtain:
String queryJson = "{\n" +
" \"query\": {\n" +
" \"match\": {\n" +
"\ "DES \": \" Software \" n" +
" }\n" +
" }\n" +
"}";
Response response = restClient.performRequest("POST"."/author_test/_search",
new HashMap<String, String>(),
new NStringEntity(queryJson,ContentType.APPLICATION_JSON));
Copy the code
The asynchronous call
The parameters of an asynchronous call are the same as those of a synchronous call, but the asynchronous call does not return a value. Instead, there is a ResponseListener callback object in the parameter, which is automatically called when the call is complete. The callback object is an interface that needs to be implemented by the programmer.
The method declaration for asynchronous calls looks like this:
public void performRequestAsync(String method, String endpoint, ResponseListener responseListener, Header... headers)
public void performRequestAsync(String method, String endpoint, Map<String, String> params,
ResponseListener responseListener, Header... headers)
public void performRequestAsync(String method, String endpoint, Map<String, String> params,
HttpEntity entity, ResponseListener responseListener, Header... headers)
Copy the code
For example, if I want to query all documents containing “software” in DES in the author_test index using an asynchronous call, the code implementation is as follows
String queryJson = "{\n" +
" \"query\": {\n" +
" \"match\": {\n" +
"\ "DES \": \" Software \" n" +
" }\n" +
" }\n" +
"}";
restClient.performRequestAsync("POST"."/author_test/_search",
new HashMap<String, String>(),
new NStringEntity(queryJson, ContentType.APPLICATION_JSON), new ResponseListener() {
public void onSuccess(Response response) {
try {
String responseData = readResposne(response);
System.out.println("******* search success ******"); System.out.println(responseData); } catch (Exception e) { e.printStackTrace(); } } public void onFailure(Exception exception) { exception.printStackTrace(); }});Copy the code
Java High Level Rest Api usage instructions
The High-level Java Api of Elastic Search is somewhat more abstract than the low-level Api. But I personally find it hard to use. And the advanced Api does not support all of the Rest Api functionality. There is an official list of features supported by the advanced Api. From this point of view, if you are just doing queries, the high-level Api interface is sufficient.
Introduction of depend on
To use the low-level Api of Elastic Search in the Maven Java project set up earlier, you must first import the low-level Api dependencies. As shown below.
<dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> The < version > 6.1.1 < / version > < / dependency >Copy the code
Setting up a client
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost", 9200, "http"),
new HttpHost("localhost", 9201, "http")));
Copy the code
The RestClient static method builder(HttpHost… The hosts) method creates a RestClientBuilder object, which is then used as an argument to the constructor of the RestHighLevelClient object to create a new advanced client object. Hosts is a variable parameter that specifies the IP addresses, ports, and protocols of nodes in an Elastic Cluster.
The method call
The high-level interface is used here to implement the function of the first query in the low-level interface. The following code
SearchRequest searchRequest = new SearchRequest("author_test");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.matchQuery("des"."Software"));
sourceBuilder.from(0);
sourceBuilder.size(5);
searchRequest.source(sourceBuilder);
SearchResponse response = restClient.search(searchRequest);
Copy the code
Other interface calls can be found in the corresponding API documentation to complete
The complete code
The final section posts the complete code.
Initialization code
This section of code is responsible for initializing the index and index document for the test. It’s important to note that as we said earlier Elastic Search is a quasi-real-time system, so if you Search right after you’ve indexed a document, you might not be able to find the data and there’s a small delay.
package com.x9710.es.test;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.entity.ContentType;
import org.apache.http.nio.entity.NStringEntity;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class IndexInitUtil {
public RestClient initLowLevelClientRestClient RestClient = restClient. builder(new HttpHost() {// Create an Elastic Search client using IP, port, and protocol"10.110.2.53", 9200, "http")).build();
try {
initIndex(restClient);
} catch (Exception e) {
e.printStackTrace();
}
return restClient;
}
public RestHighLevelClient initHighLevelClientHighLevelClient = New RestHighLevelClient() {// Create an Elastic Search client using IP, port, and protocol RestClient.builder( new HttpHost("10.110.2.53", 9200, "http"))); RestClient restClient = RestClient.builder( new HttpHost("10.110.2.53", 9200, "http")).build(); try { initIndex(restClient); } catch (Exception e) { e.printStackTrace(); } finally { try { restClient.close(); } catch (Exception e) { e.printStackTrace(); }}return highLevelClient;
}
private void initIndex(RestClient restClient) {
String authIndexDefine = "{\n" +
"\t\"settings\" : {\n" +
" \"index\" : {\n" +
" \"number_of_shards\" : 6,\n" +
" \"number_of_replicas\" : 0\n" +
" }\n" +
" },\n" +
" \"mappings\": {\n" +
" \"doc\": {\n" +
" \"properties\": {\n" +
" \t\"id\": {\"type\": \"text\"},\n" +
" \"name\": {\"type\": \"text\"},\n" +
" \"sex\": {\"type\": \"text\"},\n" +
" \"age\": {\"type\": \"integer\"},\n" +
" \"des\":{\n" +
" \t\"type\":\"text\",\n" +
" \t\"analyzer\": \"ik_max_word\",\n" +
"\t\t\t\t\t\"search_analyzer\": \"ik_max_word\"\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
"}"; HttpEntity authorIndexEntity = new NStringEntity(authIndexDefine, ContentType.APPLICATION_JSON); List<HttpEntity> authorDocs = new ArrayList<HttpEntity>(); authorDocs.add(new NStringEntity(" {\n" +
"\t\"id\":\"A1001\",\n" +
"\t\"name\ :\" Ren Yingying \",\n" +
"\t\"age\":24,\n" +
"T \ \" sex \ ", \ "female \", \ n" +
"\ T \" DES \":\"IT software engineer, skilled in Java and software architecture \"\n" +
"}", ContentType.APPLICATION_JSON));
authorDocs.add(new NStringEntity(" {\n" +
"\t\"id\":\"A1002\",\n" +
"\t\" Name \ :\" Wind clear \",\n" +
"\t\"age\":47,\n" +
"T \ \" sex \ ", \ "m \", \ n" +
"\ T \" DES \":\"IT Software technology manager, skilled in technical management process control \"\n" +
"}", ContentType.APPLICATION_JSON)); Try {/ / create author_test index restClient. PerformRequest ("PUT"."/author_test", new HashMap<String, String>(), authorIndexEntity); // Index the author_index documentfor (int i = 0; i < authorDocs.size(); i++) {
restClient.performRequest("POST"."/author_test/doc", new HashMap<String, String>(), authorDocs.get(i)); Thread.currentthread ().sleep(1000); thread.currentThread ().sleep(1000); } catch (Exception e) { e.printStackTrace(); }}}Copy the code
Low-level Api test examples
package com.x9710.es.test; import org.apache.http.entity.ContentType; import org.apache.http.nio.entity.NStringEntity; import org.codehaus.jettison.json.JSONObject; import org.elasticsearch.client.Response; import org.elasticsearch.client.ResponseListener; import org.elasticsearch.client.RestClient; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.HashMap; Public class LowLeveApiTest {public class LowLeveApiTest {public class LowLeveApiTest {public class LowLeveApiTest restClient = null; @Before public voidbefore() {
restClient = new IndexInitUtil().initLowLevelClient();
}
@Test
public void testLocateAuthorIndex() {
try {
Response response = restClient.performRequest("GET"."/author_test");
String responseData = readResposne(response);
Assert.assertTrue(new JSONObject(responseData).has("author_test"));
System.out.println(responseData);
} catch (Exception e) {
e.printStackTrace();
Assert.assertTrue(false);
}
}
@Test
public void testQueryAuthDoc() {
try {
String queryJson = "{\n" +
" \"query\": {\n" +
" \"match\": {\n" +
" \"des\": \"Java\"\n" +
" }\n" +
" }\n" +
"}";
Response response = restClient.performRequest("POST"."/author_test/_search",
new HashMap<String, String>(),
new NStringEntity(queryJson, ContentType.APPLICATION_JSON));
String responseData = readResposne(response);
JSONObject responseJson = new JSONObject(responseData);
Assert.assertTrue(responseJson.has("hits")
&& responseJson.getJSONObject("hits").getInt("total") = = 1); System.out.println(responseData); } catch (Exception e) { e.printStackTrace(); Assert.assertTrue(false);
}
}
@Test
public void testQueryAuthDocAsy() {
try {
String queryJson = "{\n" +
" \"query\": {\n" +
" \"match\": {\n" +
"\ "DES \": \" Software \" n" +
" }\n" +
" }\n" +
"}";
restClient.performRequestAsync("POST"."/author_test/_search",
new HashMap<String, String>(),
new NStringEntity(queryJson, ContentType.APPLICATION_JSON), new ResponseListener() {
public void onSuccess(Response response) {
try {
String responseData = readResposne(response);
System.out.println("******* search success ******"); System.out.println(responseData); } catch (Exception e) { e.printStackTrace(); } } public void onFailure(Exception exception) { exception.printStackTrace(); }}); } catch (Exception e) { e.printStackTrace(); Assert.assertTrue(false);
}
}
@After
public void after() {
try {
if(restClient ! = null) { restClient.performRequest("DELETE"."/author_test");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(restClient ! = null) { try { restClient.close(); } catch (Exception e) { e.printStackTrace(); } } } } private StringreadResposne(Response response) throws Exception {
BufferedReader brd = new BufferedReader(new BufferedReader(new InputStreamReader(response.getEntity().getContent())));
String line;
StringBuilder respongseContext = new StringBuilder();
while((line = brd.readLine()) ! = null) { respongseContext.append(line).append("\n");
}
//rd.close();
if (respongseContext.length() > 0) {
respongseContext.deleteCharAt(respongseContext.length() - 1);
}
returnrespongseContext.toString(); }}Copy the code
Advanced Api test samples
package com.x9710.es.test; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; /** * Public class HighLevelApiTest {** * public class HighLevelApiTest {** * public class HighLevelApiTest { RestHighLevelClient restClient = null; @Before public voidbefore() {
restClient = new IndexInitUtil().initHighLevelClient();
}
@Test
public void testQueryAuthDoc() {
try {
SearchRequest searchRequest = new SearchRequest("author_test");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.matchQuery("des"."Software"));
sourceBuilder.from(0);
sourceBuilder.size(5);
searchRequest.source(sourceBuilder);
SearchResponse response = restClient.search(searchRequest);
Assert.assertTrue(response.getHits().getTotalHits() == 2);
System.out.println(response.toString());
} catch (Exception e) {
e.printStackTrace();
Assert.assertTrue(false);
}
}
@After
public void after() {
try {
if(restClient ! = null) { restClient.indices().deleteIndex(new DeleteIndexRequest("author_test"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(restClient ! = null) { try { restClient.close(); } catch (Exception e) { e.printStackTrace(); } } } } }Copy the code
Afterword.
As mentioned earlier, the community has contributed many client libraries for Elastic Search, but has not had time to explore them. If someone has used it and thinks it is good, I hope to recommend it.
The original was published in Jane’s Book.