代码编织梦想

 

本篇博客基于前面第4篇的基础上改造的:https://blog.csdn.net/BiandanLoveyou/article/details/115773729

可以下载前面的代码:https://pan.baidu.com/s/1GnLrGGrP7nhw2Xovq3MtxQ   提取码:mhbi

这里我们需要修改一下 pom.xml 文件,引入 Google 的工具包:

完整配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.study</groupId>
    <artifactId>ElasticSearchTest</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.0.RELEASE</version>
    </parent>

    <dependencies>
        <!--Spring boot 集成包-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--web支持-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
        <!-- 引入 Google 的集合工具包 -->
        <dependency>
            <groupId>com.google.collections</groupId>
            <artifactId>google-collections</artifactId>
            <version>1.0</version>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.SR2</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>


</project>

为了测试方便,我们提前准备5条数据,使用 Kibana 管理页面进行创建。

首先创建文档并指定类型:创建文档名称为【blog】,类型为【info】。指定博客名称为【blogName】,并在索引创建的时候使用的分词器,搜索字段的值时也指定的分词器为中文分词器。博客描述【blogDesc】,博客点击数【clickCount】,博客地址【blogUrl】。注意ES的字符串类型可以指定为 text 和 Keyword。

POST /blog/info
{
  "info":{
    "properties":{
      "blogName":{
        "type":"text",
        "analyzer":"ik_smart",
        "search_analyzer":"ik_smart"
      },
      "blogDesc":{
        "type":"text",
        "analyzer":"ik_smart",
        "search_analyzer":"ik_smart"
      },
      "clickCount":{
        "type":"integer"
      },
      "blogUrl":{
        "type":"keyword"
      }
    }
  }
}

执行结果:

然后使用 Kibana 创建5条测试数据(我们先记录每条记录生成的ID):


POST /blog/info
{
  "blogName":"了解ElasticSearch",
  "blogDesc":"这个系列教程我们主要学习ElasticSearch。去到大型互联网公司,这可是必备技能!",
  "clickCount":11,
  "blogUrl":"https://blog.csdn.net/BiandanLoveyou/article/details/115710882"
}


POST /blog/info
{
  "blogName":"Windows安装ElasticSearch、Kibana、Logstash(ELK)",
  "blogDesc":"ElasticSearch是基于Java 语言开发的,因此需要JDK 环境",
  "clickCount":22,
  "blogUrl":"https://blog.csdn.net/BiandanLoveyou/article/details/115742897"
}

POST /blog/info
{
  "blogName":"简单认识 Kibana 操作ElasticSearch,ElasticSearch 的版本控制",
  "blogDesc":"一般来收,在读取数据较多的场景,使用乐观锁比较多,能提高吞吐量。在更新数据比较多的场景,使用悲观锁,能保证数据准确性。",
  "clickCount":33,
  "blogUrl":"https://blog.csdn.net/BiandanLoveyou/article/details/115772565"
}

POST /blog/info
{
  "blogName":"SpringBoot(2.2.X) 整合 最新版 ElasticSearch(7.12.X版本)",
  "blogDesc":"其实,我们可以把ElasticSearch设想成数据库!操作数据库的思想来操作即可。",
  "clickCount":44,
  "blogUrl":"https://blog.csdn.net/BiandanLoveyou/article/details/115773729"
}

POST /blog/info
{
  "blogName":"Kibana高级查询语句、DSL语言查询和过滤、中文分词器",
  "blogDesc":"Elasticsearch中默认的标准分词器对中文分词不是很友好,会将中文词语拆分成一个个中文的汉字。因此需要引入中文分词器 es-ik 插件",
  "clickCount":55,
  "blogUrl":"https://blog.csdn.net/BiandanLoveyou/article/details/115789099"
}

执行结果:

我们把执行五次的ID记录下来:

第1条:Bs9O6ngBioXCws8F2uB2
第2条:B89Q6ngBioXCws8FTuDJ
第3条:CM9Q6ngBioXCws8FcOCH
第4条:Cc9Q6ngBioXCws8FiOBV
第5条:Cs9Q6ngBioXCws8FoODN

 

接下来,我们使用 SpringBoot 代码整合查询 ElasticSearch。

entity 包下创建实体类:BlogEntity。(我们可以在IDEA 安装 lombok 插件,可以省略get、set 方法,在实体上标注 @Data 即可。为了演示方便,这里写 get、set 方法)

package com.study.entity;

import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;

/**
 * @author biandan
 * @description
 * @signature 让天下没有难写的代码
 * @create 2021-04-19 下午 9:28
 */
@Document(indexName = "blog",type = "info")
public class BlogEntity {

    @Id
    private String id;//ES 的ID

    private String blogName;//博客名称

    private String blogDesc;//博客描述
    
    private Integer clickCount;//点击数量
    
    private String blogUrl;//博客地址

    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getBlogName() {
        return blogName;
    }
    public void setBlogName(String blogName) {
        this.blogName = blogName;
    }
    public String getBlogDesc() {
        return blogDesc;
    }
    public void setBlogDesc(String blogDesc) {
        this.blogDesc = blogDesc;
    }
    public Integer getClickCount() {
        return clickCount;
    }
    public void setClickCount(Integer clickCount) {
        this.clickCount = clickCount;
    }
    public String getBlogUrl() {
        return blogUrl;
    }
    public void setBlogUrl(String blogUrl) {
        this.blogUrl = blogUrl;
    }
}

dao 包下创建 BlogDao:注意,我们继承的是 org.springframework.data.elasticsearch.repository.ElasticsearchRepository

package com.study.dao;

import com.study.entity.BlogEntity;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

/**
 * @author biandan
 * @description
 * @signature 让天下没有难写的代码
 * @create 2021-04-16 下午 11:32
 */
public interface BlogDao extends ElasticsearchRepository<BlogEntity,String> {

}

 

编写 controller 层:

package com.study.controller;

import com.google.common.collect.Lists;
import com.study.dao.BlogDao;
import com.study.entity.BlogEntity;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;

/**
 * @author biandan
 * @description
 * @signature 让天下没有难写的代码
 * @create 2021-04-16 下午 11:33
 */
@RestController
@RequestMapping(value = "/blog")
public class BlogController {

    @Autowired
    private BlogDao blogDao;


    /**
     * 根据ID查询博客信息
     *
     * @param id
     * @return
     */
    @RequestMapping(value = "/findById", method = RequestMethod.GET)
    public Optional<BlogEntity> findById(String id) {
        Optional<BlogEntity> blogEntity = blogDao.findById(id);
        return blogEntity;
    }

    /**
     * 根据条件查询所有博客列表
     * @param blogName 博客名称
     * @param blogDesc 博客描述
     * @param clickCount 点击数
     * @return
     */
    @RequestMapping(value = "/findAll", method = RequestMethod.POST)
    public List<BlogEntity> findAll(String blogName,String blogDesc,Integer clickCount){
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //模糊查询博客名称
        if(StringUtils.isNotBlank(blogName)){
            MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("blogName", blogName);
            boolQueryBuilder.must(queryBuilder);
        }
        //模糊查询博客描述
        if(StringUtils.isNotBlank(blogDesc)){
            MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("blogDesc", blogDesc);
            boolQueryBuilder.must(queryBuilder);
        }
        //根据点击数精确查询
        if(null != clickCount){
            TermQueryBuilder queryBuilder = QueryBuilders.termQuery("clickCount", clickCount);
            boolQueryBuilder.must(queryBuilder);
        }
        Iterable<BlogEntity> entities = blogDao.search(boolQueryBuilder);
        //使用Google的工具包
        List<BlogEntity> resultList = Lists.newArrayList(entities);
        return resultList;
    }

}

说明:我们使用的是单机版 ES,不使用集群版。学习的时候就学单机版好了。集群很耗电脑性能的。

OK,我们启动服务,使用 postman 做请求测试:先测试 findById 接口,这里的 id 值就是我们之前创建数据的 ID 值。

然后测试 findAll 接口:

1、测试只传递 blogName 的情况:

 

2、增加 clickCount 参数:字段之间,取的是 and 

3、增加 blogDesc 字段的查询:博客内容是:需要JDK,而我们的请求参数是:安装JDK,但是ES依然帮我们查询出来,说明ES使用了分词检索功能。

 

OK,我们看下 ElasticSearch 如何做分页查询。

主要修改 controller 层,增加 findByPage 方法即可:引入 springframework.data 的相关接口

package com.study.controller;

import com.google.common.collect.Lists;
import com.study.dao.BlogDao;
import com.study.entity.BlogEntity;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;

/**
 * @author biandan
 * @description
 * @signature 让天下没有难写的代码
 * @create 2021-04-16 下午 11:33
 */
@RestController
@RequestMapping(value = "/blog")
public class BlogController {

    @Autowired
    private BlogDao blogDao;


    /**
     * 根据ID查询博客信息
     *
     * @param id
     * @return
     */
    @RequestMapping(value = "/findById", method = RequestMethod.GET)
    public Optional<BlogEntity> findById(String id) {
        Optional<BlogEntity> blogEntity = blogDao.findById(id);
        return blogEntity;
    }

    /**
     * 根据条件查询所有博客列表
     *
     * @param blogName   博客名称
     * @param blogDesc   博客描述
     * @param clickCount 点击数
     * @return
     */
    @RequestMapping(value = "/findAll", method = RequestMethod.POST)
    public List<BlogEntity> findAll(String blogName, String blogDesc, Integer clickCount) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //模糊查询博客名称
        if (StringUtils.isNotBlank(blogName)) {
            MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("blogName", blogName);
            boolQueryBuilder.must(queryBuilder);
        }
        //模糊查询博客描述
        if (StringUtils.isNotBlank(blogDesc)) {
            MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("blogDesc", blogDesc);
            boolQueryBuilder.must(queryBuilder);
        }
        //根据点击数精确查询
        if (null != clickCount) {
            TermQueryBuilder queryBuilder = QueryBuilders.termQuery("clickCount", clickCount);
            boolQueryBuilder.must(queryBuilder);
        }
        Iterable<BlogEntity> entities = blogDao.search(boolQueryBuilder);
        //使用Google的工具包
        List<BlogEntity> resultList = Lists.newArrayList(entities);
        return resultList;
    }


    /**
     * 分页查询
     *
     * @param blogName   博客名称
     * @param blogDesc   博客描述
     * @param clickCount 点击数量
     * @param pageable   分页信息,我们可以设置默认值: page、value(每页查询数量)的值
     * @return
     */
    @RequestMapping(value = "/findByPage", method = RequestMethod.POST)
    public Page<BlogEntity> findByPage(String blogName, String blogDesc, Integer clickCount, @PageableDefault(page = 0, value = 10) Pageable pageable) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //模糊查询博客名称
        if (StringUtils.isNotBlank(blogName)) {
            MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("blogName", blogName);
            boolQueryBuilder.must(queryBuilder);
        }
        //模糊查询博客描述
        if (StringUtils.isNotBlank(blogDesc)) {
            MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("blogDesc", blogDesc);
            boolQueryBuilder.must(queryBuilder);
        }
        //根据点击数精确查询
        if (null != clickCount) {
            TermQueryBuilder queryBuilder = QueryBuilders.termQuery("clickCount", clickCount);
            boolQueryBuilder.must(queryBuilder);
        }
        Page<BlogEntity> search = blogDao.search(boolQueryBuilder, pageable);
        return search;
    }
}

重启服务,使用 postman 测试:

查询结果:

{
    "content": [
        {
            "id": "Bs9O6ngBioXCws8F2uB2",
            "blogName": "了解ElasticSearch",
            "blogDesc": "这个系列教程我们主要学习ElasticSearch。去到大型互联网公司,这可是必备技能!",
            "clickCount": 11,
            "blogUrl": "https://blog.csdn.net/BiandanLoveyou/article/details/115710882"
        },
        {
            "id": "CM9Q6ngBioXCws8FcOCH",
            "blogName": "简单认识 Kibana 操作ElasticSearch,ElasticSearch 的版本控制",
            "blogDesc": "一般来收,在读取数据较多的场景,使用乐观锁比较多,能提高吞吐量。在更新数据比较多的场景,使用悲观锁,能保证数据准确性。",
            "clickCount": 33,
            "blogUrl": "https://blog.csdn.net/BiandanLoveyou/article/details/115772565"
        }
    ],
    "pageable": {
        "sort": {
            "sorted": false,
            "unsorted": true,
            "empty": true
        },
        "offset": 0,
        "pageSize": 2,
        "pageNumber": 0,
        "paged": true,
        "unpaged": false
    },
    "facets": [],
    "aggregations": null,
    "scrollId": null,
    "maxScore": 0.41181886,
    "totalElements": 4,
    "totalPages": 2,
    "number": 0,
    "size": 2,
    "sort": {
        "sorted": false,
        "unsorted": true,
        "empty": true
    },
    "numberOfElements": 2,
    "first": true,
    "last": false,
    "empty": false
}

默认 page 的第一页是 0,size 是每页查询数量。

返回的分页参数:totalElements是总数量,totalPages是总页数,number是当前页(从0开始计算),size是每页查询数量。

代码地址:https://pan.baidu.com/s/13QyQvO3mixrBL3Ubxh2RLA  提取码:fwfw

 

 

 

 

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/BiandanLoveyou/article/details/115874372

【必看】springboot整合spring data elasticsearch-爱代码爱编程

原生java整合elasticsearch的API地址:(类似JDBC) https://www.elastic.co/guide/en/elasticsearch/client/java-api/6.2/java-doc

elasticsearch学习1—springboot整合:基本使用,分页-爱代码爱编程

1、创建springboot项目,pom依赖如下: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId>

基于springboot+elasticsearch整合分页和高亮查询-爱代码爱编程

spring-data3.1.x整合 elasticsearch只支持到6.x,如果配置连接7.x 则会报如下错误 org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are available: [{#transport#

springboot集成elasticsearch7实现全文检索及分页-爱代码爱编程

springboot集成elasticsearch7实现全文检索及分页 elasticsearch系列文章前面已经更新过三篇(https://blog.csdn.net/lsqingfeng/category_10219329.html)(建议先看下这三篇文章),分别讲解了elasticsearch7.2的安装,和springboot的集成以及简单的使用

Elasticsearch:BoolQueryBuilder 实现and or多条件分页求和查询-爱代码爱编程

Elasticsearch:BoolQueryBuilder 实现and or多条件分页求和查询 今天项目组同时遇到了一个需要es查询通过and or sum 联合查询并分页的需求,通过百度找到了对应的解决方案,在这里做个记录。 对应的需求sql条件大概是要查询a=451,b=aa 或者 a=452 b=cc 两个条件加起来的和 分页展示。 impor

SpringBoot Elasticsearch 7.x 多条件分页查询-爱代码爱编程

本文目的记录下新版本的Elasticsearch API查询使用 目录 why elasticsearchconcepthow use elasticsearch版本说明安装说明创建索引和映射新建Repository新建 service接口和实现类POJO 封装对象测试 why elasticsearch Elasticsea

SpringBoot 集成ElasticSearch(二)分页查询-爱代码爱编程

SpringBoot 集成ElasticSearch 之分页查询        SpringBoot 集成ElasticSearch 的代码,我在上一篇博客中已经写过,这边就不重复了。主要记录下service层实现类中分页查询的方法        实体类、配置信息以及新增、更新的代码在上一篇博客中,地址: SpringBoot 集成Elastic