I faced a problem connected with Elasticsearch while implementing full text search. When I try to find documents in index I face this problem
2025-08-27T09:15:59.544+03:00 ERROR 19622 --- [Muse] [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.data.elasticsearch.UncategorizedElasticsearchException: [es/search] failed: [search_phase_execution_exception] all shards failed] with root cause
co.elastic.clients.elasticsearch._types.ElasticsearchException: [es/search] failed: [search_phase_execution_exception] all shards failed
This is the dependency tree:
andrejburlacko@MacBook-Air-Andrej team28 % mvn dependency:tree | grep elasticsearch
[INFO] +- org.springframework.boot:spring-boot-starter-data-elasticsearch:jar:3.5.4:compile
[INFO] | \- org.springframework.data:spring-data-elasticsearch:jar:5.5.2:compile
[INFO] | +- co.elastic.clients:elasticsearch-java:jar:8.18.1:compile
[INFO] | +- org.elasticsearch.client:elasticsearch-rest-client:jar:8.18.1:compile
This is how I run elastic in docker:
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" \
-e "xpack.security.enabled=false" \
-e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
elasticsearch:8.18.1
This how my indexes look like:
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size dataset.size
yellow open questions _nkW3NzETNanGDBXuhiQyQ 1 1 50 0 23.7kb 23.7kb 23.7kb
yellow open tags BdaRQbRWTzSGQIWxod96VQ 1 1 0 0 249b 249b 249b
This is how mapping structure looks like for question:
{
"questions" : {
"mappings" : {
"properties" : {
"_class" : {
"type" : "keyword",
"index" : false,
"doc_values" : false
},
"id" : {
"type" : "keyword"
},
"questionText" : {
"type" : "text"
},
"score" : {
"type" : "integer"
},
"title" : {
"type" : "text"
},
"viewsCount" : {
"type" : "integer"
}
}
}
}
}
When I try search by hands through elastic api, I get my questions successfully
GET http://localhost:9200/questions/_search?q=title:производительность&pretty
{
"took": 59,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 2.920971,
"hits": [
{
"_index": "questions",
"_id": "b23e4dcc-cc13-4ba3-a354-9aee75238375",
"_score": 2.920971,
"_source": {
"_class": "ru.t1.usernamedrew.muse.entity.elastic.SearchQuestion",
"id": "b23e4dcc-cc13-4ba3-a354-9aee75238375",
"title": "SQL индексы производительность",
"questionText": "Как индексы влияют на производительность SQL запросов?",
"viewsCount": 126,
"score": 12
}
},
{
"_index": "questions",
"_id": "d54852a3-b6bd-4e99-8376-faa19cfe9a45",
"_score": 2.5565581,
"_source": {
"_class": "ru.t1.usernamedrew.muse.entity.elastic.SearchQuestion",
"id": "d54852a3-b6bd-4e99-8376-faa19cfe9a45",
"title": "Java Stream API производительность",
"questionText": "Влияет ли использование Stream API на производительность Java приложений?",
"viewsCount": 95,
"score": 9
}
}
]
}
}
This is how my search service looks like:
@Service
@RequiredArgsConstructor
public class SearchServiceImpl implements SearchService {
private final SearchQuestionRepository searchQuestionRepository;
private final SearchTagRepository searchTagRepository;
private final QuestionService questionService;
private final TagService tagService;
private final ElasticsearchOperations elasticsearchOperations;
// Поиск вопросов по заголовку
@Override
public Slice<QuestionPreviewDTO> searchQuestions(String query, Pageable pageable) {
List<UUID> questionIds = searchQuestionRepository.findByTitleContainingIgnoreCase(query, pageable) // <- it falls then findByTitleIgnoreCase try’s to make a query
.getContent().stream()
.map(SearchQuestion::getId)
.toList();
return questionService.getQuestionsByIds(questionIds, pageable);
}
// Поиск тегов по заголовку
@Override
public Slice<TagDTO> searchTags(String query, Pageable pageable) {
List<UUID> tagsIds = searchTagRepository.findByTitleContaining(query, pageable)
.getContent().stream()
.map(SearchTag::getId)
.toList();
return tagService.findAllByIds(tagsIds, pageable);
}
// Индексация вопроса
@Override
public void indexQuestion(QuestionPreviewDTO question) {
searchQuestionRepository.save(convertToSearchQuestion(question));
}
@Override
public void indexTags(Tag tags) {
// TODO
}
@Override
@Transactional
public void reindexAllQuestions() {
searchQuestionRepository.deleteAll();
int batchSize = 100;
int offset = 0;
while (true) {
Pageable pageable = PageRequest.of(offset, batchSize);
Slice<QuestionPreviewDTO> questionSlice = questionService.getQuestions(pageable);
if (questionSlice.getContent().isEmpty()) {
break;
}
List<SearchQuestion> searchQuestions = questionSlice.getContent().stream()
.map(this::convertToSearchQuestion)
.toList();
searchQuestionRepository.saveAll(searchQuestions);
offset++;
}
}
private SearchQuestion convertToSearchQuestion(QuestionPreviewDTO question) {
return SearchQuestion.builder()
.id(question.getId())
.title(question.getTitle())
.questionText(question.getQuestionText())
.viewsCount(question.getViewsCount())
.score(question.getScore())
.build();
}
}
My documents:
@Document(indexName = "questions")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SearchQuestion {
@Id
@Field(type = FieldType.Keyword)
private UUID id;
@Field(type = FieldType.Text)
private String title;
@Field(type = FieldType.Text)
private String questionText;
@Field(type = FieldType.Integer)
private Integer viewsCount;
@Field(type = FieldType.Integer)
private Integer score;
}
@Document(indexName = "tags")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SearchTag {
@Id
@Field(type = FieldType.Keyword)
private UUID id;
@Field(type = FieldType.Text)
private String title;
@Field(type = FieldType.Text)
private String description;
}
And elastic search repositories:
public interface SearchQuestionRepository extends ElasticsearchRepository<SearchQuestion, UUID> {
Slice<SearchQuestion> findByTitleContainingIgnoreCase(String title, Pageable pageable);
}
public interface SearchTagRepository extends ElasticsearchRepository<SearchTag, UUID> {
Slice<SearchTag> findByTitleContaining(String title, Pageable pageable);
}
Controller:
@RestController
@RequestMapping("/api/search")
@RequiredArgsConstructor
@Tag(name = "Контроллер поиска", description = "Поиск вопросов по названию и тегам")
public class SearchController {
private final SearchService searchService;
@GetMapping("/questions")
@Operation(summary = "Поиск вопросов по заголовку с использованием ElasticSearch")
public ResponseEntity<Slice<QuestionPreviewDTO>> searchQuestions(
@RequestParam("q") String prefix,
@PageableDefault(size = 20, sort = "createdAt") Pageable pageable) {
return ResponseEntity.ok(searchService.searchQuestions(prefix, pageable)); // falls in search service, reindex works well
}
@GetMapping("/tags")
@Operation(summary = "Поиск тега по названию с использованием ElasticSearch")
public ResponseEntity<Slice<TagDTO>> searchTags(
@RequestParam("q") String prefix,
@PageableDefault(size = 20) Pageable pageable) {
return ResponseEntity.ok(searchService.searchTags(prefix, pageable));
}
@GetMapping("/reindex")
@Operation(summary = "Реиндексация вопросов в ElasticSearch")
public void reindex() {
searchService.reindexAllQuestions();
}
}
Full text of exception:
co.elastic.clients.elasticsearch._types.ElasticsearchException: [es/search] failed: [search_phase_execution_exception] all shards failed
at co.elastic.clients.transport.ElasticsearchTransportBase.getApiResponse(ElasticsearchTransportBase.java:357) ~[elasticsearch-java-8.18.1.jar:na]
at co.elastic.clients.transport.ElasticsearchTransportBase.performRequest(ElasticsearchTransportBase.java:141) ~[elasticsearch-java-8.18.1.jar:na]
at co.elastic.clients.elasticsearch.ElasticsearchClient.search(ElasticsearchClient.java:5374) ~[elasticsearch-java-8.18.1.jar:na]
at org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate.lambda$doSearch$14(ElasticsearchTemplate.java:356) ~[spring-data-elasticsearch-5.5.2.jar:5.5.2]
at org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate.execute(ElasticsearchTemplate.java:689) ~[spring-data-elasticsearch-5.5.2.jar:5.5.2]
at org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate.doSearch(ElasticsearchTemplate.java:356) ~[spring-data-elasticsearch-5.5.2.jar:5.5.2]
at org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate.search(ElasticsearchTemplate.java:349) ~[spring-data-elasticsearch-5.5.2.jar:5.5.2]
at org.springframework.data.elasticsearch.core.SearchOperations.searchOne(SearchOperations.java:91) ~[spring-data-elasticsearch-5.5.2.jar:5.5.2]
at org.springframework.data.elasticsearch.repository.query.AbstractElasticsearchRepositoryQuery.execute(AbstractElasticsearchRepositoryQuery.java:130) ~[spring-data-elasticsearch-5.5.2.jar:5.5.2]
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:170) ~[spring-data-commons-3.5.2.jar:3.5.2]
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:158) ~[spring-data-commons-3.5.2.jar:3.5.2]
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:170) ~[spring-data-commons-3.5.2.jar:3.5.2]
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:149) ~[spring-data-commons-3.5.2.jar:3.5.2]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.2.9.jar:6.2.9]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:223) ~[spring-aop-6.2.9.jar:6.2.9]
at jdk.proxy2/jdk.proxy2.$Proxy180.findByTitleContainingIgnoreCase(Unknown Source) ~[na:na]
at ru.t1.usernamedrew.muse.service.impl.SearchServiceImpl.searchQuestions(SearchServiceImpl.java:40) ~[classes/:na] **<-- it falls when it try's to make a query in SearchQuestionRepository**
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:360) ~[spring-aop-6.2.9.jar:6.2.9]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:724) ~[spring-aop-6.2.9.jar:6.2.9]
at ru.t1.usernamedrew.muse.service.impl.SearchServiceImpl$$SpringCGLIB$$0.searchQuestions(<generated>) ~[classes/:na]
at ru.t1.usernamedrew.muse.controller.SearchController.searchQuestions(SearchController.java:30) ~[classes/:na]
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:258) ~[spring-web-6.2.9.jar:6.2.9]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:191) ~[spring-web-6.2.9.jar:6.2.9]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.2.9.jar:6.2.9]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:991) ~[spring-webmvc-6.2.9.jar:6.2.9]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:896) ~[spring-webmvc-6.2.9.jar:6.2.9]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.2.9.jar:6.2.9]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) ~[spring-webmvc-6.2.9.jar:6.2.9]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) ~[spring-webmvc-6.2.9.jar:6.2.9]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-6.2.9.jar:6.2.9]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) ~[spring-webmvc-6.2.9.jar:6.2.9]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564) ~[tomcat-embed-core-10.1.43.jar:6.0]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.2.9.jar:6.2.9]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.43.jar:6.0]
I've tried different types of queries. Tried to use NativeQuery, repositories with Page and List return types. Tried to set number_of_replicas to 0. What can I do next to fix this problem, also I tried to configure elastic with java code. All my shards are green and yellow. May be I wrote something wrong in elastic's repositories but I can't identify what's the problem. Spring Data Elastic documentation says it should work with Page and Slice.