spring-data-elasticsearch

v2026.09.24

Spring Data Elasticsearch for full-text search and analytics. Covers ElasticsearchOperations, repositories, aggregations, and index management. USE WHEN: user mentions "spring data elasticsearch", "ElasticsearchRepository", "ElasticsearchOperations", "@Document elasticsearch", "Spring Boot Elasticsearch" DO NOT USE FOR: raw Elasticsearch queries - use `elasticsearch` instead, ELK stack setup - use `elasticsearch` instead

GitHub
Install command
npx skhub add claude-dev-suite/spring-data-elasticsearch
Markdown
SKILL.md

Spring Data Elasticsearch - Quick Reference

Full Reference: See advanced.md for aggregations, autocomplete/suggestions, bulk operations, index management, and Testcontainers integration.

Deep Knowledge: Use mcp__documentation__fetch_docs with technology: spring-data-elasticsearch for comprehensive documentation.

Dependencies

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

Configuration

spring:
  elasticsearch:
    uris: http://localhost:9200
    username: ${ELASTICSEARCH_USERNAME:}
    password: ${ELASTICSEARCH_PASSWORD:}
    connection-timeout: 5s
    socket-timeout: 30s

Document Mapping

@Document(indexName = "products")
public class Product {

    @Id
    private String id;

    @Field(type = FieldType.Text, analyzer = "standard")
    private String name;

    @Field(type = FieldType.Text, analyzer = "standard")
    private String description;

    @Field(type = FieldType.Keyword)
    private String category;

    @Field(type = FieldType.Double)
    private BigDecimal price;

    @Field(type = FieldType.Integer)
    private Integer stock;

    @Field(type = FieldType.Boolean)
    private boolean active;

    @Field(type = FieldType.Date, format = DateFormat.date_hour_minute_second)
    private LocalDateTime createdAt;

    @Field(type = FieldType.Nested)
    private List<ProductAttribute> attributes;

    @Field(type = FieldType.Keyword)
    private List<String> tags;
}

Repository Pattern

public interface ProductRepository extends ElasticsearchRepository<Product, String> {

    List<Product> findByCategory(String category);
    List<Product> findByNameContaining(String name);
    List<Product> findByPriceBetween(BigDecimal min, BigDecimal max);
    List<Product> findByActiveTrue();

    // Pagination
    Page<Product> findByCategory(String category, Pageable pageable);

    // Sorting
    List<Product> findByCategoryOrderByPriceAsc(String category);

    // Count / Exists / Delete
    long countByCategory(String category);
    boolean existsByName(String name);
    void deleteByCategory(String category);
}

Custom Queries

public interface ProductRepository extends ElasticsearchRepository<Product, String> {

    @Query("""
        {
          "multi_match": {
            "query": "?0",
            "fields": ["name^3", "description", "tags"],
            "type": "best_fields",
            "fuzziness": "AUTO"
          }
        }
        """)
    Page<Product> fullTextSearch(String query, Pageable pageable);
}

ElasticsearchOperations

@Service
@RequiredArgsConstructor
public class ProductSearchService {

    private final ElasticsearchOperations elasticsearchOperations;

    public SearchHits<Product> search(ProductSearchCriteria criteria) {
        BoolQuery.Builder boolQuery = new BoolQuery.Builder();

        if (StringUtils.hasText(criteria.getQuery())) {
            boolQuery.must(MultiMatchQuery.of(m -> m
                .query(criteria.getQuery())
                .fields("name^3", "description", "tags")
                .fuzziness("AUTO")
            )._toQuery());
        }

        if (StringUtils.hasText(criteria.getCategory())) {
            boolQuery.filter(TermQuery.of(t -> t
                .field("category")
                .value(criteria.getCategory())
            )._toQuery());
        }

        NativeQuery query = NativeQuery.builder()
            .withQuery(boolQuery.build()._toQuery())
            .withPageable(PageRequest.of(criteria.getPage(), criteria.getSize()))
            .build();

        return elasticsearchOperations.search(query, Product.class);
    }
}

Best Practices

DoDon't
Use appropriate field typesMap everything as text
Define proper analyzersUse default for all
Use filters for exact matchesUse match for keywords
Paginate large result setsFetch all documents at once

When NOT to Use This Skill

  • Raw Elasticsearch API - Use elasticsearch skill for REST API
  • ELK stack setup - Use elasticsearch skill
  • Primary database - Elasticsearch is for search, not ACID transactions

Anti-Patterns

Anti-PatternProblemSolution
Refresh after each writePerformance degradationUse refresh_interval, batch
Deep pagination with from/sizeMemory issuesUse search_after
Mapping all as textPoor search, high diskUse appropriate field types
No index lifecycleDisk exhaustionConfigure ILM policies
Fetching all fieldsWasted bandwidthUse source filtering

Quick Troubleshooting

ProblemDiagnosticFix
Connection failedCheck Elasticsearch runningStart ES, check URI, SSL
Index not foundCheck index nameCreate index, check @Document
Mapping conflictCheck field typesReindex with correct mapping
Search returns nothingCheck analyzerTest with _analyze API
Version conflictCheck @VersionHandle OptimisticLockingFailureException

Production Checklist

  • Cluster configured (3+ nodes)
  • Shards and replicas set
  • Index lifecycle management
  • Proper mapping defined
  • Analyzers configured
  • Bulk operations for indexing
  • Monitoring enabled
  • Security enabled

Reference Documentation

Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.24

Published

Sep 24, 2026

Category

Uncategorized

License

MIT

Source path

skills/databases/spring-data-elasticsearch

Default branch

main

Latest commit

9496306

Tree SHA

fe4e2f1