本文最后更新于:2021年6月15日 晚上
网上大多通过 java 操作 es 使用的都是 TransportClient,而介绍使用 SpringDataElasticSearch 的文章相对比较少,笔者也是摸索了许久,接下来本文介绍 SpringDataElasticSearch 的 api 使用,更加方便的进行查询。
系列文章
环境依赖
本文以及后续 es 系列文章都基于 5.5.3 这个版本的 elasticsearch ,这个版本比较稳定,可以用于生产环境。
本文项目基于 SpringBoot 2.0.4.RELEASE 进行构建,首先引入 Spring Data ElasticSearch 的依赖。
注意:因为是 Spring Boot 项目,所以引入的依赖是 spring-boot-starter-data-elasticsearch,而不是直接引入 spring-data-elasticsearch。
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency>
|
Spring Data ElasticSearch 与 ElasticSearch 有对应关系
spring data elasticsearch |
elasticsearch |
3.1.x |
6.2.2 |
3.0.x |
5.5.0 |
2.1.x |
2.4.0 |
2.0.x |
2.2.0 |
1.3.x |
1.5.2 |
而本文使用的 SpringBoot 2.0.4.RELEASE 自动依赖的 Spring Data ElasticSearch 版本是 3.0.9.RELEASE,对应的 elasticsearch 版本是 5.5.x,可知依赖是正确的版本。
创建 Document 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| @Data @Document(indexName = "novel", type = "book", createIndex = false) public class Book implements Serializable {
private static final long serialVersionUID = 8504604495927552402L;
@Id private Integer id;
private Integer words;
private String intro;
private String name;
private Integer sort;
private Boolean vip;
private Integer site;
private String author;
private Integer collection;
private Integer click;
private Integer popularity;
private Integer goods;
private Integer status;
@JsonFormat (shape = JsonFormat.Shape.STRING, pattern ="yyyy-MM-dd HH:mm:ss") private Date updatetime;
}
|
这个 Document 类封装了索引的全部字段信息,注意字段名称要与索引类型的字段名称一致。
创建 Repository 接口
| public interface BookRepository extends ElasticsearchRepository<Book, Integer> {
}
|
用过 SpringDataJPA 的朋友都应该知道,ElasticsearchRepository 的两个泛型分别为 Documet 以及 Document 的主键类型。
创建测试类
| @Slf4j @SpringBootTest @RunWith(SpringRunner.class) public class BookRepositoryTest {
@Autowired private BookRepository bookRepository;
}
|
演示简单查询
匹配查询(MatchQuery)
进行模糊匹配查询,这里演示的是通过 name 这个字段进行查询
| @Test public void findBook() { MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("name", "火爆娱乐天王"); bookRepository.search(matchQuery) .forEach(e -> log.info("作品信息:{}", e)); }
|
项查询(TermQuery)
完全匹配查询,这里演示查询 id 为 2 的数据
| @Test public void findBook() {
TermQueryBuilder termQuery = QueryBuilders.termQuery("id", 2); bookRepository.search(termQuery) .forEach(e -> log.info("作品信息:{}", e)); }
|
范围查询(Range Query)
范围查询,这里演示查询字数在 0-30w 之间的作品
| @Test public void findBook() { RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("words").gt(0).lt(300000); bookRepository.search(rangeQuery) .forEach(e -> log.info("作品信息:{}", e)); }
|
注意:如果对时间进行范围查询,注意不能传递 Date 对象或者 毫秒值,只能传递 yyyy-MM-dd HH:mm:ss 格式的字符串时间参数。
复合查询
以上演示了几个基本查询,但是如果要实现多筛选条件的查询,就需要把多个基本查询进行组合,这里就用到了 bool 查询
现在来实现这个查询
BookQuery 参数封装
使用 BookQuery 类封装查询参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| @Data public class BookQuery {
private String queryString;
private Integer page = 1;
private Integer size = 20;
private Integer wordsBegin;
private Integer wordsEnd;
private Integer sort;
private Boolean vip;
private Integer site;
private Integer collection;
private Integer click;
private Integer popularity;
private Integer goods;
private Integer status;
private Date updatetime; }
|
查询测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| @Test public void findBook() {
BookQuery query = new BookQuery(); query.setQueryString("魔"); query.setSite(2); query.setSort(29); query.setVip(true); query.setWordsBegin(0); query.setWordsEnd(500000); query.setPage(1); query.setSize(10);
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
MultiMatchQueryBuilder matchQuery = QueryBuilders.multiMatchQuery(query.getQueryString(), "name", "intro", "author"); boolQuery.must(matchQuery);
TermQueryBuilder siteQuery = QueryBuilders.termQuery("site", query.getSite()); boolQuery.filter(siteQuery); TermQueryBuilder sortQuery = QueryBuilders.termQuery("sort", query.getSort()); boolQuery.filter(sortQuery); TermQueryBuilder vipQuery = QueryBuilders.termQuery("vip", query.getVip()); boolQuery.filter(vipQuery); RangeQueryBuilder wordsQuery = QueryBuilders.rangeQuery("words").gt(query.getWordsBegin()).lt(query.getWordsEnd()); boolQuery.filter(wordsQuery);
Sort sort = Sort.by(Sort.Direction.DESC, "click"); PageRequest pageRequest = PageRequest.of(query.getPage() - 1, query.getSize(), sort);
log.info("{}", boolQuery); bookRepository.search(boolQuery, pageRequest) .forEach(e -> log.info("作品信息:{}", e)); }
|
查出结果:
| 2018-09-12 22:33:05.750 INFO 25896 --- [ main] i.g.mosiki.search.BookRepositoryTest : 作品信息:Book(id=7, words=345004, intro= 推荐《寻龙传》《魂摄天下》 作品属玄幻异界大陆风格! 可惜频道不能更改只能在奇幻混! 书友群:292... , name=灭魔成圣, sort=29, vip=true, site=2, author=等待潇湘诗社, collection=13, click=63263, popularity=2314, goods=5353, status=0, updatetime=Tue Sep 04 16:54:15 CST 2018) 2018-09-12 22:33:05.751 INFO 25896 --- [ main] i.g.mosiki.search.BookRepositoryTest : 作品信息:Book(id=9, words=233000, intro= 一名地球的平凡的少年,因为一场游戏,获得死神的传承,从而穿越到另外一片陌生的大陆,从此开启了一段传奇的人生,九天星河,吾乃死神,掌控生死,判夺罪恶,我从没见过地狱,因为我的名字,便代表地狱,吾乃死神,吾名林天。(PS:单女主,爽文不虐心,主角以杀证道,杀该杀之人,不圣母,略腹黑) 各位书友要是觉得《带着死神去穿越》还不错的话请不要忘记向您QQ群和微博里的朋友推荐哦!带着死神去穿越最新章节,带着死神去穿越无弹窗,带着死神去穿越全文阅读. , name=带着死神去穿越, sort=29, vip=true, site=2, author=梦侍, collection=6326, click=523, popularity=135, goods=34252, status=0, updatetime=Thu Dec 28 04:53:07 CST 2017) 2018-09-12 22:33:05.751 INFO 25896 --- [ main] i.g.mosiki.search.BookRepositoryTest : 作品信息:Book(id=5, words=490000, intro= 富家子弟墨浞因为发现了村子中的秘密,在良心与亲情的折磨下,逃到了边境小城。因为一个香-艳而又恐怖的梦,墨浞经历了一些诡异的事,从而得知自己的前世与今生的使命。踏上藏地,历经磨难,克服了自己的心魔,战胜了... , name=伏魔, sort=29, vip=true, site=2, author=一叶style, collection=526, click=9, popularity=41516, goods=7687, status=0, updatetime=Thu Sep 06 04:54:05 CST 2018)
|
最后
SpringDataElasticSearch 入门就到这里了,是不是很简单呢?
本文示例项目地址:https://github.com/Mosiki/SpringDataElasticSearchQuickStartExample
有疑问?
欢迎来信,给我写信
参考