Spring Boot中基于ElasticsearchRepository实现特定条件书籍查询的问题
解决ElasticsearchRepository自定义统计查询的方案
首先纠正你方法签名里的两处拼写错误:Timestomp → Timestamp,另外你的需求是统计数量,所以方法返回值应该是long而非List<Books>,更合理的方法签名应该是:
long countBooks(List<Long> bookIds, Long authorId, Timestamp from, Timestamp to);
假设你的Books实体类定义如下(需确保字段与Elasticsearch索引映射匹配):
import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.FieldType; import java.sql.Timestamp; @Document(indexName = "books") public class Books { private Long bookId; private Long authorId; @Field(type = FieldType.Date) private Timestamp publishTime; // 假设出版时间字段名为publishTime // getter、setter、构造方法省略 }
下面提供三种实现方式:
1. 方法命名查询(最简便)
Spring Data Elasticsearch支持通过方法名自动生成查询,遵循命名规则即可:
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; import java.sql.Timestamp; import java.util.List; public interface BookRepository extends ElasticsearchRepository<Books, Long> { // 按命名规则自动生成统计查询 long countByBookIdInAndAuthorIdAndPublishTimeBetween(List<Long> bookIds, Long authorId, Timestamp from, Timestamp to); }
命名规则说明:
countBy:表示统计数量BookIdIn:匹配bookId在给定列表中AndAuthorId:匹配authorId等于指定值PublishTimeBetween:匹配publishTime在from和to之间
2. @Query注解自定义DSL查询
如果需要更灵活的查询逻辑,可以用@Query注解直接编写Elasticsearch DSL:
import org.springframework.data.elasticsearch.annotations.Query; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; import java.sql.Timestamp; import java.util.List; public interface BookRepository extends ElasticsearchRepository<Books, Long> { @Query(""" { "bool": { "must": [ {"terms": {"bookId": "?0"}}, {"match": {"authorId": "?1"}}, {"range": {"publishTime": {"gte": "?2", "lte": "?3"}}} ] } } """) long countCustomBooks(List<Long> bookIds, Long authorId, Timestamp from, Timestamp to); }
注意:DSL中的?0、?1对应方法参数的索引(从0开始),Elasticsearch会自动将Timestamp类型参数转换为符合date格式的字符串。
3. 用ElasticsearchOperations构建查询(复杂场景适用)
如果需要动态拼接查询条件,可借助ElasticsearchOperations:
import org.springframework.data.elasticsearch.core.ElasticsearchOperations; import org.springframework.data.elasticsearch.core.query.Criteria; import org.springframework.data.elasticsearch.core.query.CriteriaQuery; import org.springframework.stereotype.Service; import java.sql.Timestamp; import java.util.List; @Service public class BookService { private final ElasticsearchOperations elasticsearchOperations; public BookService(ElasticsearchOperations elasticsearchOperations) { this.elasticsearchOperations = elasticsearchOperations; } public long countBooks(List<Long> bookIds, Long authorId, Timestamp from, Timestamp to) { Criteria criteria = new Criteria("bookId").in(bookIds) .and("authorId").is(authorId) .and("publishTime").between(from, to); CriteriaQuery query = new CriteriaQuery(criteria); return elasticsearchOperations.count(query, Books.class); } }
注意事项
- 确保Elasticsearch索引中
publishTime字段的类型为date,否则区间查询会失效 - 如果实体类中用
LocalDateTime替代Timestamp,Spring Data Elasticsearch同样支持自动转换,可根据实际情况选择类型
内容的提问来源于stack exchange,提问作者FPS Bard
相关产品推荐
相关产品推荐

