0

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.

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.