1. Overview
In this article, we will dive into some key concepts related to full-text search engines, with a special focus on Elaticsearch.
Since this is a Java-driven article, we will not provide detailed step-by-step instructions on how to set up Elaticsearch and show how this program works, instead, we will target the client. Java, and how to use key features like index creation, delete, get and search.
2. Setup
To install Elaticsearch, please refer to the official setup guide.
The installation process is quite simple, just download the zip / tar package and run the elaticsearch script file (elSTERearch.bat for Windows users).
By default, Elaticsearch listens on port 9200 for HTTP queries. We can verify that it successfully launched by opening http: // localhost: 9200 / URL in your favorite browser:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
{ "name" : "GEpcsab", "cluster_name" : "elasticsearch", "cluster_uuid" : "z3FfAe6gRMmSmeWBIOihJg", "version" : { "number" : "5.6.10", "build_hash" : "b727a60", "build_date" : "2018-06-06T15:48:34.860Z", "build_snapshot" : false, "lucene_version" : "6.6.1" }, "tagline" : "You Know, for Search" } |
3. Maven Configuration
Now that we have up and running the basic Elaticsearch cluster, let’s move straight to the Java client. First of all, we need to have the Maven dependency declared in pom.xml:
1 2 3 4 5 6 |
<dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>5.6.0</version> </dependency> |
You can always check out the latest versions hosted by Maven Central with the link provided previously.
4. Java API
Before moving straight to using the main Java API features, we need to initialize the client application:
1 2 3 4 5 |
Client client = new PreBuiltTransportClient( Settings.builder().put("client.transport.sniff", true) .put("cluster.name","elasticsearch").build()) .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300)); |
a. Indexing Documents
The prepareIndex () function allows to store an arbitrary JSON document and make it searchable:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
@Test public void givenJsonString_whenJavaObject_thenIndexDocument() { String jsonObject = "{"age":10,"dateOfBirth":1471466076564," +""fullName":"John Doe"}"; IndexResponse response = client.prepareIndex("people", "Doe") .setSource(jsonObject, XContentType.JSON).get(); String id = response.getId(); String index = response.getIndex(); String type = response.getType(); long version = response.getVersion(); assertEquals(Result.CREATED, response.getResult()); assertEquals(0, version); assertEquals("people", index); assertEquals("Doe", type); } |
When running the test, be sure to declare the path.home variable, otherwise, there will be the following exception:
1 2 |
java.lang.IllegalStateException: path.home is not configured |
After running the Maven command: mvn clean install -Des.path.home = C: elastic, the JSON document will be stored with everyone as an index.
Note that any JSON Java library can be used to create and process documents. If you are not familiar with any of these, you can use the Elaticsearch helper to create your own JSON documents.
1 2 3 4 5 6 7 8 9 10 11 |
XContentBuilder builder = XContentFactory.jsonBuilder() .startObject() .field("fullName", "Test") .field("dateOfBirth", new Date()) .field("age", "10") .endObject(); IndexResponse response = client.prepareIndex("people", "Doe") .setSource(builder).get(); assertEquals(Result.CREATED, response.getResult()); |
b. Querying Indexed Documents
Now that we have a searchable index JSON document, we can proceed and search using prepareSearch ():
1 2 3 4 5 6 |
SearchResponse response = client.prepareSearch().execute().actionGet(); List<SearchHit> searchHits = Arrays.asList(response.getHits().getHits()); List<Person> results = new ArrayList<Person>(); searchHits.forEach( hit -> results.add(JSON.parseObject(hit.getSourceAsString(), Person.class))); |
The results returned by the actionGet () method are called Entrances, each time accessing a JSON document that matches a search request.
In this case, the resulting list contains all data stored in the cluster. Note that in this example, we are using the FastJson library to convert JSON String to Java objects.
1 2 3 4 5 6 7 |
SearchResponse response = client.prepareSearch() .setTypes() .setSearchType(SearchType.DFS_QUERY_THEN_FETCH) .setPostFilter(QueryBuilders.rangeQuery("age").from(5).to(15)) .execute() .actionGet(); |
c. Retrieving and Deleting Documents
The prepareGet () and prepareDelete () methods allow you to receive or delete a JSON document from the cluster using its id:
1 2 3 4 5 6 |
GetResponse response = client.prepareGet("people","Doe","1").get(); String age = (String) response.getField("age").getValue(); // Process other fields DeleteResponse response = client.prepareDelete("people", "Doe", "5") .get(); |
The syntax is quite simple, you just need to specify the index and the type value along with the id of the object.
5. QueryBuilders Examples
The QueryBuilders class provides many static methods that are used as dynamic matches to find specific items in the cluster. While using the prepareSearch () method to search for specific JSON documents in the cluster, we can use query builders to customize the search results.
This is a list of the most common uses for the QueryBuilders API. The matchAllQuery () method returns a QueryBuilder object that matches all documents in the cluster:
1 2 |
QueryBuilder matchAllQuery = QueryBuilders.matchAllQuery(); |
RangeQuery () matches documents that have the value of a field within a certain range:
1 2 3 |
QueryBuilder matchDocumentsWithinRange = QueryBuilders .rangeQuery("price").from(15).to(100) |
Provide the field name – for example, FullName and the corresponding value – for example, John Doe, The matchQuery () method matches all documents with the exact field value:
1 2 3 |
QueryBuilder matchSpecificFieldQuery= QueryBuilders .matchQuery("fullName", "John Doe"); |
We can also use the multiMatchQuery () method to build a multi-field version of the matching query:
1 2 3 |
QueryBuilder matchSpecificFieldQuery= QueryBuilders.matchQuery( "Text I am looking for", "field_1", "field_2^3", "*_field_wildcard"); |
6. Conclusion
In this quick article, we looked at how to use ElasticSearch’s Java API to perform some common features related to full-text search engines.
Source: Baeldung.