和我一起打造个简单搜索之SpringDataElasticSearch入门

网上大多通过 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 类

@Data
@Document(indexName = "novel", type = "book", createIndex = false)
public class Book implements Serializable {

    private static final long serialVersionUID = 8504604495927552402L;

    /**
     * 需要添加 @Id 标识主键
     */
    @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 类封装查询参数

@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;
}

查询测试

@Test
public void findBook() {

    BookQuery query = new BookQuery();
    query.setQueryString("魔");
    query.setSite(2);// 1 是男生 2 是女生
    query.setSort(29); // 29 是玄幻
    query.setVip(true);// 查询 vip 作品
    query.setWordsBegin(0); // 查询字数在 0-25w 之间的作品
    query.setWordsEnd(500000);
    query.setPage(1);// 分页页码
    query.setSize(10);// 每页显示数

    // 复合查询
    BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

    // 以下为查询条件, 使用 must query 进行查询组合
    MultiMatchQueryBuilder matchQuery = QueryBuilders.multiMatchQuery(query.getQueryString(), "name", "intro", "author");
    boolQuery.must(matchQuery);

    // 以下为过滤筛选条件,使用 filter 比使用 must query 性能要好
    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");
    // 分页 同时根据 点击数 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

有疑问?

欢迎来信,给我写信

参考

  • https://blog.csdn.net/tianyaleixiaowu/article/details/77965257
  • https://tech.youzan.com/search-engine1/#43filteredquery

原文地址:https://www.cnblogs.com/vcmq/p/9966688.html

时间: 2024-10-09 15:26:02

和我一起打造个简单搜索之SpringDataElasticSearch入门的相关文章

和我一起打造个简单搜索之SpringDataElasticSearch关键词高亮

前面几篇文章详细讲解了 ElasticSearch 的搭建以及使用 SpringDataElasticSearch 来完成搜索查询,但是搜索一般都会有搜索关键字高亮的功能,今天我们把它给加上. 系列文章 一.和我一起打造个简单搜索之ElasticSearch集群搭建 二.和我一起打造个简单搜索之ElasticSearch入门 三.和我一起打造个简单搜索之IK分词以及拼音分词 四.和我一起打造个简单搜索之Logstash实时同步建立索引 五.和我一起打造个简单搜索之SpringDataElasti

和我一起打造个简单搜索之Logstash实时同步建立索引

用过 Solr 的朋友都知道,Solr 可以直接在配置文件中配置数据库连接从而完成索引的同步创建,但是 ElasticSearch 本身并不具备这样的功能,那如何建立索引呢?方法其实很多,可以使用 Java API 的方式建立索引,也可以通过 Logstash 的插件 logstash-input-jdbc 完成,今天来探讨下如何使用 logstash-input-jdbc 完成全量同步以及增量同步. 环境 本文以及后续 es 系列文章都基于 5.5.3 这个版本的 elasticsearch

和我一起打造个简单搜索之ElasticSearch集群搭建

我们所常见的电商搜索如京东,搜索页面都会提供各种各样的筛选条件,比如品牌.尺寸.适用季节.价格区间等,同时提供排序,比如价格排序,信誉排序,销量排序等,方便了用户去找到自己心里理想的商品. 站内搜索对于一个网站几乎是标配,只是搜索的强大与否的区别,有的网站只支持关键词模糊搜索,而淘宝,京东提供了精细的筛选条件,同时支持拼音搜索等更方便的搜索方式. 由于笔者在一家做网络文学的公司工作,所以实现就是以小说为商品的搜索,具体可以参考起点网小说的搜索. 如图所示,起点网的搜索提供了关键词搜索和排序条件以

和我一起打造个简单搜索之IK分词以及拼音分词

elasticsearch 官方默认的分词插件,对中文分词效果不理想,它是把中文词语分成了一个一个的汉字.所以我们引入 es 插件 es-ik.同时为了提升用户体验,引入 es-pinyin 插件.本文介绍这两个 es 插件的安装. 环境 本文以及后续 es 系列文章都基于 5.5.3 这个版本的 elasticsearch ,这个版本比较稳定,可以用于生产环境. ik 分词器 和 pinyin 分词器在 github 仓库可以找到,注意版本与 elasticsearch 的版本需要对应,本文使

参与过三次搜索引擎发展转折的百度,为什么要回归“简单搜索”

相信在搜索引擎技术产品化的二十余年间,我们早已经习惯了搜索引擎的商业化.不过在最近的数博会上,李彦宏却展示了一款名为"简单搜索"的语音交互搜索App,并且声明简单搜索永无广告. 相信很多人也曾想象过这样一款产品--通过语音发问,得出最简单的答案.不过可能大多数人没有想到,推出这款产品的是百度.很长一段时间内,百度的搜索引擎商业化一直为人诟病.但这次百度率先推出永无广告的语音交互搜索,无疑是在搜索引擎的技术和产品形式上都进行了重要创新. 当我们在质疑大企业的创新能力时常常会忽视一点,在技

《ElasticSearch6.x实战教程》之简单搜索、Java客户端(上)

第五章-简单搜索 众里寻他千百度 搜索是ES的核心,本节讲解一些基本的简单的搜索. 掌握ES搜索查询的RESTful的API犹如掌握关系型数据库的SQL语句,尽管Java客户端API为我们不需要我们去实际编写RESTful的API,但在生产环境中,免不了在线上执行查询语句做数据统计供产品经理等使用. 数据准备 首先创建一个名为user的Index,并创建一个student的Type,Mapping映射一共有如下几个字段: 创建名为user的Index PUT http://localhost:9

专题一、简单搜索 - Virtual Judge

很久以前刷完了Virtual Judge上的简单搜索专题,现总结如下: POJ 1321 由于题目的数据范围比较小,可以直接dfs暴力.读入时记录每个空位的位置,保存在pX[]以及pY[]数组中.暴力的时候统计当前处理第几个空格以及当前处理到了第几行即可. #include <iostream> #include <memory.h> using namespace std; const int MAX = 128; long long ans; int N, K, nCnt; b

[.NET] 一步步打造一个简单的 MVC 电商网站 - BooksStore(二)

一步步打造一个简单的 MVC 电商网站 - BooksStore(二) 本系列的 GitHub地址:https://github.com/liqingwen2015/Wen.BooksStore 前:<一步步打造一个简单的 MVC 电商网站 - BooksStore(一)> 简介 上一次我们尝试了:创建项目架构.创建域模型实体.创建单元测试.创建控制器与视图.创建分页和加入样式,而这一节我们会完成两个功能,分类导航与购物车. 主要功能与知识点如下: 分类.产品浏览.购物车.结算.CRUD(增删

java 模拟简单搜索

Java 模拟简单搜索 实体类 package org.dennisit.entity; /** * * * @version : 1.0 * * @author : 苏若年 <a href="mailto:[email protected]">发送邮件</a> * * @since : 1.0 创建时间: 2013-4-8 下午04:51:03 * * @function: TODO * */ public class Medicine { private I