本篇博客基于前面第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
转载:https://blog.csdn.net/BiandanLoveyou/article/details/115874372