Spring Boot + Elasticsearch: Full‑Text Search Integration Guide
This article walks through integrating Spring Boot with Elasticsearch to enable fuzzy search, keyword highlighting, tokenized queries, and real‑time data sync, covering environment setup, Maven dependencies, application.yml configuration, entity annotations, CRUD via Repository, advanced queries with RestTemplate, IK analyzer usage, common pitfalls, and synchronization strategies.
Why Use Elasticsearch
When a project needs fuzzy search, keyword highlighting, tokenized queries, hot‑search recommendations, product search, or full‑text article search, MySQL like %xxx% becomes insufficient. Elasticsearch provides distributed storage, petabyte‑scale data handling, millisecond response times, and powerful analysis and aggregation capabilities, making it the standard backend for full‑text search.
Applicable Scenarios
E‑commerce product and shop search
Article/blog/document full‑text search
Log retrieval and operational monitoring (ELK)
Hot‑search, suggestion, recommendation completion
Multi‑condition filtering, sorting, highlighting
High‑concurrency fuzzy queries
Environment
Spring Boot 2.x/3.x
Elasticsearch 7.x (example uses 7.x)
IK Analyzer (required for Chinese tokenization)
Kibana (optional for DSL debugging)
Maven Dependencies
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>application.yml Configuration
spring:
elasticsearch:
uris: http://localhost:9200
# 8.x requires username/password
# username: elastic
# password: 123456Core Annotations
@Document: maps a class to an ES index; attributes include indexName, shards,
replicas @Id: document primary key @Field: defines field type and analyzer; e.g., type = FieldType.Text, analyzer = "ik_max_word" for tokenized text, type = FieldType.Keyword for exact matches
Entity Example (Article Search)
package com.demo.entity;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import java.time.LocalDateTime;
@Data
@Document(indexName = "article", shards = 1, replicas = 0)
public class ArticleES {
@Id
private Long id;
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
private String title;
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
private String content;
@Field(type = FieldType.Keyword)
private String author;
@Field(type = FieldType.Integer)
private Integer viewCount;
@Field(type = FieldType.Keyword)
private String category;
@Field(type = FieldType.Date)
private LocalDateTime createTime;
}Two Access Methods
Spring Boot can interact with Elasticsearch via:
ElasticsearchRepository : simple CRUD similar to JPA.
ElasticsearchRestTemplate / ElasticsearchTemplate : supports complex highlighting, aggregations, and multi‑condition queries.
Method 1 – Repository CRUD
package com.demo.repository;
import com.demo.entity.ArticleES;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface ArticleESRepository extends ElasticsearchRepository<ArticleES, Long> {
// Find by title
List<ArticleES> findByTitle(String title);
} @Service
@RequiredArgsConstructor
public class ArticleESService {
private final ArticleESRepository repository;
// Save or update
public ArticleES save(ArticleES article) { return repository.save(article); }
// Find by ID
public ArticleES findById(Long id) { return repository.findById(id).orElse(null); }
// Find all
public Iterable<ArticleES> findAll() { return repository.findAll(); }
// Delete by ID
public void deleteById(Long id) { repository.deleteById(id); }
}Method 2 – RestTemplate for Complex Queries
@Autowired
private ElasticsearchRestTemplate restTemplate;
public List<ArticleES> search(String keyword) {
// Build query: multi‑match on title and content
NativeSearchQuery query = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.multiMatchQuery(keyword, "title", "content"))
.withHighlightFields(
new HighlightBuilder.Field("title")
.preTags("<span style='color:red'>")
.postTags("</span>"),
new HighlightBuilder.Field("content")
.preTags("<span style='color:red'>")
.postTags("</span>")
)
.withPageable(PageRequest.of(0, 10))
.withSort(SortBuilders.fieldSort("viewCount").order(SortOrder.DESC))
.build();
SearchHits<ArticleES> hits = restTemplate.search(query, ArticleES.class);
List<ArticleES> results = new ArrayList<>();
for (SearchHit<ArticleES> hit : hits.getSearchHits()) {
ArticleES article = hit.getContent();
Map<String, List<String>> highlights = hit.getHighlightFields();
if (highlights.containsKey("title")) {
article.setTitle(highlights.get("title").get(0));
}
if (highlights.containsKey("content")) {
article.setContent(highlights.get("content").get(0));
}
results.add(article);
}
return results;
}Common Query Examples
Exact match (must)
.withQuery(QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("category", "Java"))
.must(QueryBuilders.rangeQuery("viewCount").gte(100)))Should (OR) query
.withQuery(QueryBuilders.boolQuery()
.should(QueryBuilders.matchQuery("title", "SpringBoot"))
.should(QueryBuilders.matchQuery("content", "Redis")))Range query
QueryBuilders.rangeQuery("viewCount").gte(100).lte(10000)Fuzzy query
QueryBuilders.fuzzyQuery("title", "SpringBoot")Aggregation (group by category)
.withAggregation(AggregationBuilders.terms("group_category").field("category"))Data Synchronization (MySQL ↔ ES)
Simple approach : update ES whenever MySQL insert or update occurs.
Middleware : use Canal or Debezium to listen to binlog and sync automatically.
Scheduled task : suitable when real‑time sync is not required.
IK Analyzer (Chinese Tokenizer)
Must be installed to correctly split Chinese text.
Supports custom dictionaries (e.g., Java, SpringBoot, cloud‑native).
Two modes: ik_max_word (finest granularity) and ik_smart (coarser granularity).
Important Notes
Version compatibility : Spring Boot and Elasticsearch versions must match; otherwise startup fails.
IK installation : missing IK leads to poor Chinese search results.
Keyword field limitation : keyword type cannot perform fuzzy search; use text with analyzer.
Highlighting fails if field names do not match the query.
Deep pagination has performance issues; prefer scroll or search_after.
Index existence : ensure index is created automatically or manually before querying.
Conclusion
Integrating Spring Boot with Elasticsearch follows the workflow: add dependencies → configure connection → define document entities → build queries. Use Repository for simple CRUD, and RestTemplate for complex highlighting, multi‑condition queries, and aggregations.
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.
Java Tech Workshop
Focused on Java backend technologies, sharing fundamentals, multithreading, JVM, the Spring ecosystem, microservices, distributed systems, high concurrency, source‑code analysis, and practical experience. Continuously delivers high‑quality original content, interview guides, and learning roadmaps to help Java developers progress from beginner to advanced, enhancing technical skills and core competitiveness.
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.
