Integrating Elasticsearch with Spring Boot for Full‑Text Search in a Microservice Architecture
This tutorial demonstrates how to integrate Elasticsearch into a Spring Boot microservice, covering component selection, Maven configuration, client setup, index creation, data insertion, complex query execution, synchronization of question data, and front‑end search handling, all illustrated with complete Java code examples.
Introduction
The article builds on a previous discussion of Elasticsearch full‑text search principles and shows how to integrate Elasticsearch into a Spring Boot application and a Spring Cloud microservice project to achieve full‑text search for a large question‑answer dataset.
Elasticsearch Component Library
Elasticsearch 7.4.2 is used with the official Elasticsearch Rest High Level Client. The official documentation URL is
https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high.html. Both the high‑level and low‑level clients exist, but the high‑level client is preferred for its richer features.
Integrating the Search Service
1.1 Add Search Service Module
A new module passjava-search is created using Spring Initializr with the Spring Web dependency.
1.2 Configure Maven Dependencies
Add the following dependency to passjava-search/pom.xml:
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.4.2</version>
</dependency>Set the Elasticsearch version property to 7.4.2 to avoid version mismatches.
<properties>
<elasticsearch.version>7.4.2</elasticsearch.version>
</properties>Include the common module dependency:
<dependency>
<groupId>com.jackson0714.passjava</groupId>
<artifactId>passjava-common</artifactId>
<version>0.0.1‑SNAPSHOT</version>
</dependency>1.3 Register Service with Nacos
Add the following properties to src/main/resources/application.properties:
spring.application.name=passjava-search
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.namespace=passjava-searchAnnotate the main class with @EnableDiscoveryClient and exclude the datasource auto‑configuration.
@EnableDiscoveryClient
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class PassjavaSearchApplication {
public static void main(String[] args) {
SpringApplication.run(PassjavaSearchApplication.class, args);
}
}1.4 Add Elasticsearch Configuration Class
Create PassJavaElasticsearchConfig.java to provide a RestHighLevelClient bean:
package com.jackson0714.passjava.search.config;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class PassJavaElasticsearchConfig {
@Bean
public RestHighLevelClient restHighLevelClient() {
return new RestHighLevelClient(
RestClient.builder(new HttpHost("192.168.56.10", 9200, "http")));
}
}1.5 Test Client Auto‑Loading
In PassjavaSearchApplicationTests inject the client and print it:
@SpringBootTest
class PassjavaSearchApplicationTests {
@Qualifier("restHighLevelClient")
@Autowired
private RestHighLevelClient client;
@Test
void contextLoads() {
System.out.println(client);
}
}1.6 Simple Data Insertion Test
Insert a User document into the users index:
IndexRequest request = new IndexRequest("users");
request.id("1");
User user = new User();
user.setUserName("PassJava");
user.setAge("18");
user.setGender("Man");
String jsonString = JSON.toJSONString(user);
request.source(jsonString, XContentType.JSON);
IndexResponse response = client.index(request, RequestOptions.DEFAULT);
System.out.println(response);Verify insertion with GET users/_search and observe the returned JSON fields.
1.7 Complex Query Example
Demonstrates a search on the bank index with address matching, age aggregation, and average salary aggregation. The request is built with SearchRequest, SearchSourceBuilder, and appropriate aggregations, then executed and parsed.
Synchronizing ES Data
3.1 Define Search Model
The question index stores title and answer fields (both analyzed with ik_smart), plus id and typeName.
"title": {"type": "text", "analyzer": "ik_smart"},
"answer": {"type": "text", "analyzer": "ik_smart"}3.2 Create Index
PUT question
{
"mappings": {
"properties": {
"id": {"type": "long"},
"title": {"type": "text", "analyzer": "ik_smart"},
"answer": {"type": "text", "analyzer": "ik_smart"},
"typeName": {"type": "keyword"}
}
}
}3.3 Define ES Model Class
@Data
public class QuestionEsModel {
private Long id;
private String title;
private String answer;
private String typeName;
}3.4 Save Data to ES
When a question is saved to MySQL, the service copies properties to QuestionEsModel (using BeanUtils.copyProperties) and calls the passjava-search service to index the document.
searchFeignService.saveQuestion(esModel);Querying ES Data
4.1 Request Parameters
Three parameters are defined: keyword (full‑text match), id (exact match), and pageNum (pagination).
@Data
public class SearchParam {
private String keyword;
private String id;
private Integer pageNum;
}4.2 Response Structure
@Data
public class SearchQuestionResponse {
private List<QuestionEsModel> questionList;
private Integer pageNum;
private Long total;
private Integer totalPages;
}4.3 Assemble Search Request
Create a SearchRequest for the question index, add a multiMatchQuery on title, answer, and typeName, set from and size for pagination, then execute.
SearchRequest request = new SearchRequest("question");
SearchSourceBuilder builder = new SearchSourceBuilder();
BoolQueryBuilder bool = QueryBuilders.boolQuery();
if (param.getKeyword() != null) {
bool.must(QueryBuilders.multiMatchQuery(param.getKeyword(), "title", "answer", "typeName"));
}
if (param.getId() != null) {
bool.filter(QueryBuilders.termQuery("id", param.getId()));
}
builder.query(bool);
builder.from((param.getPageNum() - 1) * 5);
builder.size(5);
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);4.4 Format Search Results
Extract hits, deserialize each hit into QuestionEsModel, and populate pagination fields.
SearchHits hits = response.getHits();
SearchHit[] searchHits = hits.getHits();
List<QuestionEsModel> list = new ArrayList<>();
for (SearchHit hit : searchHits) {
QuestionEsModel model = JSON.parseObject(hit.getSourceAsString(), QuestionEsModel.class);
list.add(model);
}
SearchQuestionResponse result = new SearchQuestionResponse();
result.setQuestionList(list);
result.setPageNum(param.getPageNum());
result.setTotal(hits.getTotalHits().value);
result.setTotalPages((int) Math.ceil((double) hits.getTotalHits().value / 5));Conclusion
The article provides a step‑by‑step guide on integrating Elasticsearch with a Spring Boot microservice, covering client configuration, index creation, data synchronization, and query implementation, enabling efficient full‑text search for large question‑answer datasets.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Wukong Talks Architecture
Explaining distributed systems and architecture through stories. Author of the "JVM Performance Tuning in Practice" column, open-source author of "Spring Cloud in Practice PassJava", and independently developed a PMP practice quiz mini-program.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
