• Elasticsearch


    Elasticsearch 概述

    Elasticsearch下载

    官方下载链接

    https://www.elastic.co/cn/downloads/past-releases#elasticsearch

    什么是Elasticsearch

    elastic:富有弹性的

    search:搜索

    我们可以把它简称为ES,但是搜索它的资料时(例如百度)还是使用Elasticsearch进行搜索更准确

    这个软件不是SpringCloud提供的,它也不针对微服务环境的项目来开发

    Elasticsearch和redis\mysql一样,不仅服务于java语言,其它语言也可以使用。它的功能也类似一个数据库,能高效的从大量数据中搜索匹配指定关键字的内容,它也将数据保存在硬盘中。

    这样的软件有一个名称全文搜索引擎,它本质就是一个java项目,使用它进行数据的增删改查就是访问这个项目的控制器方法(url路径)。

    ES的底层技术

    ES使用了java的一套名为Lucene的API,这个API提供了全文搜索引擎核心操作的接口,相当于搜索引擎的核心支持,ES是在Lucene的基础上进行了完善,实现了开箱即用的搜索引擎软件。

    市面上和ES功能类似的软件有:Solr/MongoDB。

    为什么需要Elasticsearch

    数据库进行模糊查询效率严重低下,所有关系型数据库都有这个缺点(mysql\mariaDB\oracle\DB2等),在执行类似下面模糊查询时

    select * from spu where spu_name like '%鼠标%'
    
    • 1

    测试证明一张千万级别的数据表进行模糊查询需要20秒以上,当前互联网项目要求"三高"的需求下,这样的效率肯定不能接受,Elasticsearch主要是为了解决数据库模糊查询性能低下问题的。ES进行优化之后,从同样数据量的ES中查询相同条件数据,效率能够提高100倍以上。

    数据库索引简介

    所谓的索引(index)其实就是数据目录(类比一下新华字典里面的目录),通常情况下,索引是为了提高查询效率的。

    数据库索引分两大类:

    • 聚集索引
    • 非聚集索引

    聚集索引就是数据库保存数据的物理顺序依据,默认情况下就是主键id,所以按id查询数据库中的数据效率非常高。

    非聚集索引:如果想在非主键列上添加索引,就是非聚集索引了。例如我们在数据库表中存在一个姓名列,我们为姓名列创建索引,在创建索引时,会根据姓名内容来创建索引,例如"张三丰" 这个姓名,创建索引后查询效率就会明显提升。

    如果没有索引,这样的查询就会引起效率最低的"逐行搜索",就是一行一行的查这个数据的姓名是不是张三丰,效率就会非常低。

    模糊查询时因为’%鼠标%',使用的是前模糊条件,使用索引必须明确前面的内容是什么,前模糊查询是不能使用索引的,只能是全表的逐行搜索,所以效率非常低(优化sql语句中就有减少前模糊查询sql语句)。

    所以当我们项目中设计了根据用户输入关键字进行模糊查询时,需要使用全文搜索引擎来优化。

    索引面试题

    1.创建的索引会占用硬盘空间

    2.创建索引之后,对该表进行增删改操作时,会引起索引的更新,所以效率会降低

    3.对数据库进行批量新增时,先删除索引,增加完毕之后再创建

    4.不要对数据样本少的列添加索引

    5.模糊查询时,查询条件前模糊的情况,是无法启用索引的

    6.每次从数据表中查询的数据的比例越高,索引的效果越低

    7.当我们执行查询时,where条件后应该先查询有索引的列

    Elasticsearch运行原理

    要想使用ES提高模糊查询效率,首先要将数据库中的数据复制到ES中,在新增数据到ES的过程中,ES可以对指定的列进行分词索引保存在索引库中形成倒排索引结构。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-90WkQmlf-1667814143133)(1664265320621.jpg)]

    Elasticsearch的启动

    压缩包280M左右,复制到没有中文,没有空格的目录下解压,双击bin\elasticsearch.bat运行。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xx32CWkI-1667814143134)(image-20220510103755913.png)]

    双击之后可能会看到下面的dos界面

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ITclsWtS-1667814143136)(image-20220510104124826.png)]
    可能会因为自己的Java环境变量出现问题,解决方案可以看:
    链接: windows10环境elasticsearch7.10.X启动闪退和报错问题

    这个界面不能关闭,一旦关闭ES就停止了。

    验证ES的运行状态,浏览器输入地址:localhost:9200看到如下内容即可。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ipqi6iMZ-1667814143137)(image-20220510104421448.png)]

    mac系统启动命令:

    tar -xvf elasticsearch-7.6.2-darwin-x86_64.tar.gz 
    cd elasticsearch-7.6.2/bin 
    ./elasticsearch
    
    • 1
    • 2
    • 3

    linux系统启动命令:

    tar -xvf elasticsearch-7.6.2-linux-x86_64.tar.gz
    cd elasticsearch-7.6.2/bin
    ./elasticsearch
    
    • 1
    • 2
    • 3

    ES基本使用

    ES启动完成后,我们要学习如何操作它,我们已经讲过,操作ES是对ES发送请求,我们创建一个项目search,在这个子项目中创建一个专门发送各种类型请求的文件来操作ES。

    然后项目pom文件如下

    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0modelVersion>
        <parent>
            <groupId>cn.tedugroupId>
            <artifactId>csmallartifactId>
            <version>0.0.1-SNAPSHOTversion>
            <relativePath/> 
        parent>
        <groupId>cn.tedugroupId>
        <artifactId>searchartifactId>
        <version>0.0.1-SNAPSHOTversion>
        <name>searchname>
        <description>Demo project for Spring Bootdescription>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starterartifactId>
            dependency>
    
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-testartifactId>
                <scope>testscope>
            dependency>
        dependencies>
        
    project>
    
    • 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

    下面创建一个能够向ES发送请求的文件,这种能够向指定url发送请求的文件格式称之为http client(http 客户端)。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X2jylvzh-1667814143138)(image-20220825162421614.png)]

    文件类型叫HTTP Request文件,可以起名为elasticsearch。

    先从最简单的请求开始,向es发送指令:

    ### 三个#是注释,也是分隔符,每个发送指令的请求必须使用分隔符分隔
    GET http://localhost:9200
    
    ### 测试ES的分词功能,运行分词,查看分词结果
    POST http://localhost:9200/_analyze
    Content-Type: application/json
    
    {
      "text": "my name is hanmeimei",
      "analyzer": "standard"
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    analyze:分析

    analyzer:分析者(分词器)

    standard是ES默认的分词器,“analyzer”: "standard"是可以省略的

    standard这个分词器只能对英文等西文字符(有空格的),进行正确分词,但是中文分词不能按空格分,按这个分词器分词,每个字都会形成分词,这样的结果不能满足我们日常的搜索需要。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W0tDjL5R-1667814143140)(image-20220510112849958.png)]

    我们解决中文不能正确分词的问题,实际上要引入一个中文常见词语的词库,分词时按照词库中的词语分词即可。

    我们可以使用免费的中文分词器词库插件IK来实现中文分词效果

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-04Si52RU-1667814143141)(image-20220510113345841.png)]

    安装插件之后要重启ES才能生效,关闭Es窗口之后再双击elasticsearch.bat文件运行即可,ES启动之后,将中文分词器设置完成,在运行分词。

    {
      "text": "罗技激光鼠标",
      "analyzer": "ik_smart"
    }
    
    • 1
    • 2
    • 3
    • 4

    再次运行分词测试,应该看到正常的中文分词效果,但是词库的容量有限,比较新的网络名词和较新出现的人名是不在词库中的(这就很尴尬了)。

    ik分词插件的使用

    我们安装的ik实际上不只一个分词器,实际上除了ik_smart之外还有ik_max_word。

    POST http://localhost:9200/_analyze
    Content-Type: application/json
    
    {
      "text": "北京冬季奥林匹克运动会顺利闭幕",
      "analyzer": "ik_smart"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    POST http://localhost:9200/_analyze
    Content-Type: application/json
    
    {
      "text": "北京冬季奥林匹克运动会顺利闭幕",
      "analyzer": "ik_max_word"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    上面的两个分词器运行分词,结果会有非常明显的区别。

    总结区别如下:

    ik_smart

    • 优点:特征是粗略快速的将文字进行分词,占用空间小,查询速度快;

    • 缺点:分词的颗粒度大,可能跳过一些重要分词,导致查询结果不全面,查全率低。

    ik_max_word

    • 优点:特征是详细的文字片段进行分词,查询时查全率高,不容易遗漏数据;
    • 缺点:因为分词太过详细,导致有一些无用分词,占用空间较大,查询速度慢。

    使用ES操作数据

    ES是一个数据库性质的软件,可以执行增删改查操作,只是他操作数据不使用sql,数据的结构和关系型数据库也不同。

    我们先了解一下ES保存数据的结构

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-90bBejIS-1667814143142)(day06/image-20220510142049346.png)]

    • ES启动后,ES服务可以创建多个index(索引),index可以理解为数据库中表的概念;

    • 一个index可以创建多个保存数据的document(文档),一个document理解为数据库中的一行数据;

    • 一个document中可以保存多个属性和属性值,对应数据库中的字段(列)和字段值。

    SpringBoot 操作 Elasticsearch

    Spring Data简介

    原生状态下,我们使用JDBC连接数据库,因为代码过于繁琐,所以改为使用Mybatis框架,在ES的原生状态下,我们java代码需要使用socket访问ES,但是也是过于繁琐,我们可以使用SpringData框架简化,Spring Data是Spring提供的一套连接各种第三方数据源的框架集,我们需要使用的是其中连接ES的Spring Data Elasticseatrch。

    官方网站:https://spring.io/projects/spring-data

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b8z8iIoL-1667815959658)(image-20220510152943325.png)]

    官网中列出了SpringData支持连接操作的数据源列表,下面我们就按照SpringDataElasticsearch的步骤对ES进行操作。

    添加依赖和配置

    就使用我们之前创建的search模块来操作ES

    pom文件添加依赖

    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0modelVersion>
        <parent>
            <groupId>cn.tedugroupId>
            <artifactId>csmallartifactId>
            <version>0.0.1-SNAPSHOTversion>
            <relativePath/> 
        parent>
        <groupId>cn.tedugroupId>
        <artifactId>searchartifactId>
        <version>0.0.1-SNAPSHOTversion>
        <name>searchname>
        <description>Demo project for Spring Bootdescription>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starterartifactId>
            dependency>
    
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-testartifactId>
                <scope>testscope>
            dependency>
            
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-data-elasticsearchartifactId>
            dependency>
    
        dependencies>
    
    project>
    
    • 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

    application.properties添加配置

    # 配置ES所在的ip地址和端口号信息
    spring.elasticsearch.rest.uris=http://localhost:9200
    
    # 设置日志门槛
    logging.level.cn.tedu.search=debug
    # SpringDataElasticsearch框架中有一个转换输出信息的类,它也需要设置为debug
    logging.level.org.elasticsearch.client.RestClient=debug
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    创建和ES关联的实体类

    和其他数据库一样,我们操作ES时也需要一个类似实体类的数据类,作为操作ES的数据载体。

    search项目创建entity包,在包中创建Item(商品)类。

    @Data
    @Accessors(chain = true)    // 支持链式Set赋值
    @AllArgsConstructor         // 自动生成当前类的全参构造方法
    @NoArgsConstructor          // 自动生成当前类的无参构造方法
    // @Document注解标记表示当前类是对应ES框架的一个实体类
    // 属性indexName指定ES中的索引名称,运行时,如果这个索引不存在SpringData会自动创建这个索引
    @Document(indexName = "items")
    public class Item implements Serializable {
    
        // SpringData通过@Id注解标记当前实体类主键
        @Id
        private Long id;
        // SpringData 标记title字段需要支持分词,并定义分词器
        @Field(type = FieldType.Text,
                analyzer = "ik_max_word",
                searchAnalyzer = "ik_max_word")
        private String title;
        // Keyword类型是不分词的字符串类型
        @Field(type = FieldType.Keyword)
        private String category;
        @Field(type = FieldType.Keyword)
        private String brand;
        @Field(type = FieldType.Double)
        private Double price;
        // imgPath是图片路径,他不会称之为搜索条件,所以可以不创建索引,节省空间
        // 设置index = false,就是不创建索引
        // 但是需要注意,不创建索引并不是不保存这个数据,ES会保存这个数据
        @Field(type = FieldType.Keyword,index = false)
        private String imgPath;
    
        // images/2022/10/28/a0cf86-70adcc12-712918-ac878323.jpg
    
    }
    
    • 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

    创建操作ES的持久层

    我们使用SpringData连接ES,需要知道SpringData框架对持久层的命名规则,持久层规范名称为repository(仓库),创建这个包,包中创建接口ItemRepository。

    // Repository是spring家族对框架持久层的规范命名
    @Repository
    public interface ItemRepository extends ElasticsearchRepository<Item,Long> {
        // ItemRepository接口要继承SpringData框架提供的父接口ElasticsearchRepository
        // 一旦继承,当前接口就可以编写连接ES操作数据的代码了,
        // 继承了父接口后,SpringData会根据我们泛型中编写的Item找到对应的索引
        // 会对这个索引自动生成基本的增删改查方法,我们自己无需再编写
        // ElasticsearchRepository<[要操作的\关联的实体类名称],[实体类主键的类型]>
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    测试ES

    如果没有测试包,创建test测试包,如果没有测试类,创建测试类。

    编写测试

    // 注意必须有@SpringBootTest注解才能顺利测试!
    @SpringBootTest
    @Slf4j
    class SearchApplicationTests {
    
        @Autowired
        private ItemRepository itemRepository;
    
        // 执行单增
        @Test
        void addOne() {
            // 实例化Item对象
            Item item=new Item()
                    .setId(1L)
                    .setTitle("罗技激光无线游戏鼠标")
                    .setCategory("鼠标")
                    .setBrand("罗技")
                    .setPrice(188.0)
                    .setImgPath("/1.jpg");
            // 利用SpringDataElasticsearch提供的新增方法,完成Item新增到ES
            itemRepository.save(item);
            System.out.println("ok");
        }
    
        // 单查
        @Test
        void getOne(){
            // SpringDataElasticsearch提供了按id查询数据的方法
            // 返回值是一个Optional类型的对象,理解为只能保存一个元素的集合
            // 需要内容时直接调用get方法即可获取其中对象
            Optional<Item> optional=itemRepository.findById(1L);
            Item item=optional.get();
            System.out.println(item);
    
        }
    
        // 批量增
        @Test
        void addList(){
            // 实例化一个List对象,用户添加要保存到ES的Item对象
            List<Item> list=new ArrayList<>();
            list.add(new Item(2L,"罗技激光有线办公鼠标","鼠标",
                                "罗技",9.9,"/2.jpg"));
            list.add(new Item(3L,"雷蛇机械无线游戏键盘","键盘",
                                "雷蛇",262.0,"/3.jpg"));
            list.add(new Item(4L,"微软有线静音办公鼠标","鼠标",
                                "微软",190.0,"/4.jpg"));
            list.add(new Item(5L,"罗技机械有线背光键盘","键盘",
                                "罗技",236.0,"/5.jpg"));
            itemRepository.saveAll(list);
            System.out.println("ok");
    
        }
    
        // 全查
        @Test
        void getAll(){
            // SpringData框架提供的全查ES中对应实体类的所有数据的方法
            Iterable<Item> items=itemRepository.findAll();
            for(Item item : items){
                System.out.println(item);
            }
            System.out.println("------------------------------------");
            items.forEach(item -> System.out.println(item));
    
        }
    
    
    }
    
    • 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
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69

    SpringData自定义查询

    SpringData框架提供的基本增删改查方法并不能完全满足我们的业务需要,如果是针对当前Es数据,进行个性化的自定义查询,那还是需要自己编写查询代码,就像我们要实现根据关键词查询商品信息一样,完成类似数据库中的模糊查询。

    单条件查询

    我们查询需求为输出所有数据中title属性包含"游戏"这个分词的商品信息

    参考数据库中模糊查询

    select * from item where title like '%游戏%'
    
    • 1

    我们使用SpringDataES进行查询,本质上还是相当于ES文档中执行的查询语句

    在SpringData框架下,ItemRepository接口中实现更加简单

    // SpringData实现自定义查询
    // 我们要编写遵循SpringData给定格式的方法名
    // SpringData会根据方法名称自动推断出查询目的,生成查询语句完成操作
    // query(查询):表达当前方法是一个查询方法,等价于sql中的select
    // Item/Items:确定要查询的实体类(对应的索引),不带s是查询单个对象的,带s的查集合
    // By(通过/根据):标识开始设置查询条件的单词,等价于sql中的where
    // Title:要查询的字段,可以是Item实体类中声明的任何字段
    // Matches(匹配):执行查询条件的操作,Matches是匹配字符串类型的关键字,支持分词等价sql中的like
    
    Iterable<Item> queryItemsByTitleMatches(String title);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    下面可以开始在测试类中进行测试查询

    // 单条件自定义查询
    @Test
    void queryOne(){
        // 查询ES中items索引数据,title字段包含"游戏"分词的数据
        Iterable<Item> items=itemRepository.queryItemsByTitleMatches("游戏");
        items.forEach(item -> System.out.println(item));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    上面代码运行时底层运行的查询语句为:

    ### 单条件搜索
    POST http://localhost:9200/items/_search
    Content-Type: application/json
    
    {
      "query": {"match": { "title":  "游戏" }}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    多条件查询

    在相对复杂的查询逻辑下,经常使用多个条件来定位查询需要的数据,这样就需要逻辑运算符"and"/“or”。

    ItemRepository接口中添加多条件的查询方法

    // 多条件查询
    // 多个条件之间要使用and或or来分隔,表示多个条件间的逻辑关系
    // 如果我们想按照Title和Brand进行多条件查询
    // 多个条件时,方法名就要按规则编写多个条件,参数也要对应条件的个数来变化
    // 声明的参数会按照顺序赋值给方法名中的条件,和参数名称无关
    Iterable<Item> queryItemsByTitleMatchesAndBrandMatches(
                                        String title,String brand);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    测试代码如下

    // 多条件自定义查询
    @Test
    void queryTwo(){
        // 查询ES中,items索引里,title字段包含"游戏",并且品牌是"罗技"的数据
        Iterable<Item> items=itemRepository
                .queryItemsByTitleMatchesAndBrandMatches("游戏","罗技");
        items.forEach(item -> System.out.println(item));
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    底层运行的请求

    ### 多字段搜索
    POST http://localhost:9200/items/_search
    Content-Type: application/json
    
    {
      "query": {
        "bool": {
          "must": [
            { "match": { "title": "游戏"}},
            { "match": { "brand": "罗技"}}
          ]
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    当查询条件关系为And时,查询语句关键字为must;当查询条件关系为Or时,查询语句关键字为should。

    排序查询

    默认情况下从ES中查询获得的数据排序依据是ES查询得出的相关性分数(score),但是如果想改变这个排序就需要在查询方法上添加新的关键字。

    在ItemRepository接口添加具备排序功能的查询方法

    // 排序查询
    Iterable<Item> queryItemsByTitleMatchesOrBrandMatchesOrderByPriceDesc(
            String title,String brand);
    
    • 1
    • 2
    • 3

    测试代码如下

    // 自定义排序查询
    @Test
    void queryOrder(){
        Iterable<Item> items=itemRepository
                .queryItemsByTitleMatchesOrBrandMatchesOrderByPriceDesc(
                                                   "游戏","罗技");
        items.forEach(item -> System.out.println(item));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    底层运行的代码:

    ### 多字段搜索
    POST http://localhost:9200/items/_search
    Content-Type: application/json
    
    {
      "query": {
        "bool": {
          "should": [
            { "match": { "title": "游戏"}},
            { "match": { "brand": "罗技"}}
          ]
        }
      },"sort":[{"price":"desc"}]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    分页查询

    SpringData框架支持完成分页查询。

    需要在ItemRepository接口中修改方法的参数和返回值就可以实现

    // 分页查询
    // 返回值类型需要修改为Page类型,这个类型既可以保存从ES中查询到的数据又可以保存
    // 当前分页查询的分页信息:当前页,总页数,总条数,每页条数,有没有上一页,有没有下一页等
    // 分页查询方法参数要添加一个Pageable,必须放在现有所有参数的后面
    // 它可以设置要查询的页码和每页的条数
    
    Page<Item> queryItemsByTitleMatchesOrBrandMatchesOrderByPriceDesc(
            String title, String brand, Pageable pageable);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    测试代码

    // 自定义分页查询
    @Test
    void queryPage(){
        int page=2;             // 要查询的页码,写1表示查询第一页
        int pageSize=2;         // 每页条数的设置
        Page<Item> pages=itemRepository
                .queryItemsByTitleMatchesOrBrandMatchesOrderByPriceDesc(
                     "游戏","罗技", PageRequest.of(page-1,pageSize));
        pages.forEach(item -> System.out.println(item));
        // pages对象包含的分页信息输出
        System.out.println("总页数:"+pages.getTotalPages());
        System.out.println("总条数:"+pages.getTotalElements());
        System.out.println("当前页:"+(pages.getNumber()+1));
        System.out.println("每页条数:"+pages.getSize());
        System.out.println("是否是首页:"+pages.isFirst());
        System.out.println("是否是末页:"+pages.isLast());
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
  • 相关阅读:
    旅游卡免费旅游的使用条件有哪些?
    【Pytorch深度学习实战】(12)神经风格迁移(Neural Style Transfer)
    服务器向客户端推送消息之——WebSocket详细使用
    解决windows端口占用
    NoSQL数据库使用场景以及架构介绍
    Mac nginx安装,通过源码安装教程
    PTA天梯赛训练 7-8 查验身份证 (15分)
    最强AI换脸工具Rope使用教程,Rope整合包下载【全网最全安装步骤】
    函数递归(C语言)(详细过程!)
    UE中制作棋盘格材质效果
  • 原文地址:https://blog.csdn.net/weixin_43121885/article/details/127735880