目录
Spring Data ElasticSearch 查询方式
4 Spring Data ElasticSearch 查询方式
4.1 使用 Repository 继承的方法操作文档
ElasticsearchTemplate 主要负责操作索引库,对文档的操作我们使用可以使用 Repository 中继承的方法
4.2 命名规则查询文档
es 的命名规则跟 jpa 基本一致,常见的如下:
4.3 使用原生方式查询文档
ES 本身支持一些特殊查询,如模糊查询,对语句先分词后查询等,我们可以在接口方 法上使用@Query 注解自定义查询条件。如:
@Query("{\n" +
" \"fuzzy\": {\n" +
" \"productName\": {\n" +
" \"value\":\"elasticsearch\",\n" +
" \"max_expansions\":1\n" +
" }\n" +
" }\n" +
"}")
List<Product> findByProductNameFuzzy(String productName);
@Query("{\n" +
" \"query_string\": {\n" +
" \"query\": \"?0\",\n" +
" \"default_field\": \"productName\"\n" +
" }\n" +
"}")
List<Product> findByProductNameString(String productName);
4.4 分页查询
使用 repository 自定义或继承的方法时,在参数中添加 Pageable 参数,返回值为 Page 类型即可完成分页查询。
4.5 使用 Template 操作 ElasticSearch
SpringDataElasticsearch 也支持 Template 方式操作,我们需要向类中注入一个 ElasticsearchRestTemplate 对象。
4.5.1 操作索引
(1) template 调用 IndexOperations indexOps(Class clazz),获得索引操作对象。
(2) IndexOperations 的常用方法:
create():创建索引。注:该方法无法设置索引结构,框架遗留 bug
delete():删除索引
4.5.2 增删改文档
template 操作文档的常用方法:
save():新增/修改文档
delete():删除文档
4.5.3 查询文档
template 的 search 方法可以查询文档:
SearchHits search(Query query, Class clazz):查询文档,query 是查询条件对象,clazz 是结果类型。
1. 普通查询: 构建 Query 对象
// 构建查询条件
// 单词查询
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("productDesc", "科幻");
// 模糊查询
FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery("productName", "三体
").maxExpansions(2);
// 先分词后查询
QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery("我喜欢三
体").defaultField("productName");
// 构建 Query 对象
NativeSearchQuery query = new NativeSearchQueryBuilder()
.withQuery(termQueryBuilder).build();
查询并处理结果:
// 查询
SearchHits<Product> search = template.search(query, Product.class);
System.out.println(search.getMaxScore());
System.out.println(search.getTotalHits());
for (SearchHit<Product> productSearchHit : search) {
System.out.println(productSearchHit.getContent());
}
2. 复杂条件查询
String productName = "三";
String productDesc = null;
// 构建查询条件
BoolQueryBuilder defaultQueryBuilder = QueryBuilders.boolQuery();
if(productName != null){
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("productName", productName);
defaultQueryBuilder.should(termQueryBuilder);
}
if(productDesc != null){
FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery("productDesc", productDesc).maxExpansions(2);
defaultQueryBuilder.should(fuzzyQueryBuilder);
}
// 构建 Query 对象
NativeSearchQuery query = new NativeSearchQueryBuilder()
.withQuery(defaultQueryBuilder).build();
3. 分页查询
// 构建 Query 对象
Pageable pageable = PageRequest.of(0,5);
NativeSearchQuery query = new NativeSearchQueryBuilder()
.withQuery(defaultQueryBuilder)
.withPageable(pageable)
.build();
// 查询
SearchHits<Product> search = template.search(query, Product.class);
// 封装页面对象
Page<Product> page = new PageImpl(search.toList(),pageable,search.getTotalHits());
System.out.println(page.getTotalElements());
System.out.println(page.getTotalPages());
System.out.println(page.getContent());
4.排序查询
SortBuilder sortBuilder = SortBuilders.fieldSort("id").order(SortOrder.DESC);
NativeSearchQuery query = new NativeSearchQueryBuilder()
.withQuery(defaultQueryBuilder)
.withSort(sortBuilder)
.build();
六、 Spring Data MongoDB
1 概念
MongoDB 是一个跨平台的,面向文档的非关系型数据库,是非关系数据库当中功能 最丰富,最像关系型数据库的产品。它支持的数据结构非常松散,是类似 JSON 的一种格式,因此可以存储比较复杂的数据类型。
MongoDB 主要有以下几个概念:
文档(document)相当于关系数据库中的一条记录
多个文档组成一个集合(collection),相当于关系型数据库的表。
多个集合组织在一起就是数据库(database),一个 MongoDB 实例支持多个数据库。
MongoDB 跟关系型数据库中概念的对比:
Spring Data MongoDB 是 SpringData 技术封装了 mongodb-driver 之后的产物, 它可以用更加简单的方式操作 MongoDB。
2 安装 MongoDB
2.1. 安装 MongoDB
2.2. 安装 MongoDB 可视化工具 RoBo 3T
3.3. RoBo 3T 连接 MongoDB,创建一个 databas
3 Spring Data MongoDB 项目搭建
1. 创建 SpringBoot 项目,创建时加入 Spring Data MongoDB 起步依赖。
2. 写配置文件
spring:
data:
mongodb:
uri: mongodb://localhost:27017/数据库名
3. 创建实体类
@Document("article")
public class Article {
@Id
private Integer id;
private String title;
private String content;
// 省略 getter/setter,构造方法,tostring
}
4. 创建 Repository 接口继承 MongoRepository 接口
5. 测试类中注入 Repository
4 Spring Data MongoDB 常用方法
1. Repository 接口继承的方法
2. 分页查询
3. 命名规则查询
七、 Spring Data Solr
1 概念
Solr 是基于 Apache Lucene 构建的搜索引擎工具。功能类似 ElasticSearch,在 Solr 中有以下概念:
collection/core:同一种数据格式的集合,可以对照数据库中的一张表,在 solr 集群中称为 collection,在单机环境中称为 core。
document:document 是 Solr 索引和搜索的最基本单元,类似于关系数据库表 中的一条记录。
filed:字段,或者称为域,可理解为数据库中的一张表中的字段。
Solr 跟关系型数据库中概念的对比:
注:Spring 从 2020 年起已经停止 Spring Data Solr 的维护,Spring 更加推荐使用 ElasticSearch 作为搜索引擎。SpringBoot 在 2.4.0 版本之后也不支持 Spring Data Solr 模块,我们此处简单学习即可。
2 安装 Solr
1 解压 solr 的 zip 压缩包。
2 进入 solr 安装路径下的 bin 目录,打开 cmd 控制台,输入 solr.cmd start 启动 solr
3 访问 http://localhost:8983/solr,进入 solr 图形化管理界面
3 Spring Data Solr 入门案例
1 创建 core
(1)在 solr 安装目录下 server\solr 创建一个文件夹用于保存 core 的数据
(2)将 solr 安装目录下 server\solr\configsets\_default\conf 文件夹拷贝到刚刚创 建的目录下。
(3)在 solr 图形化管理界面点击 add core,创建 core
2 创建 springboot 项目,加入 Spring Data Solr 模块,springboot 版本不要高于 2.4.0
3 写配置文件
spring:
data:
solr:
host: http://localhost:8983/solr/
4 创建实体类
@SolrDocument(solrCoreName = "product")
public class Product {
@Field
private String id;
@Field
private String productName;
@Field
private String productDesc;
// 省略 getter/setter,构造方法,tostring
}
5 创建 Repository 接口继承 SolrCrudRepository 接口
6 测试类中注入 Repository,Template 对象,测试保存方法
4 Spring Data Solr 常用方
1 Template 对象的方法
2 Repository 接口继承的方法
3 分页查询
4 命名规则查询
八、 Spring Data 案例
1 案例介绍 下面我们通过一个案例来综合使用 Spring Data 技术,案例以电商网站中的商品管理 为背景,涉及商品管理、查询最新商品、评论管理、商品搜索等功能。下面具体分析:
商品数据分为基础信息和商品详情,分别存储在 mysql 的商品表和商品详情表中。
最新商品查询的是最近添加的商品,实际开发中可以展示推广的产品。访问量比较大,
采用 redis 存储。 商品评论数据量大,数据价值较低,存放在 mongodb 中。 全文检索使用 ES 实现,本案例直接向 ES 中插入数据,实际开发中可以使用 logstash 从数据库同步。
2 功能分析
3 项目搭建
3.1 软件准备
开启 mysql、Redis、RedisDesktopManager、ElasticSearch、kibana、MongoDB、 Robo 3t,在 mysql 中创建数据库。
3.2 创建项目
创建 Springboot 项目,起步依赖需要引入:spring data jpa、mysql driver、spring data elasticsearch、spring data redis、spring data mongodb、spring web
3.3 配置文件
server:
port: 80
context-path: /
spring:
# 数据源
datasource:
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql:///shopping?serverTimezone=GMT%2b8
username: root
password: root
jpa:
database: MySQL
show-sql: true
generate-ddl: true
hibernate:
ddl-auto: update
naming_strategy: org.hibernate.cfg.ImprovedNamingStrategy
# 解决属性使用驼峰命名法无法与数据库字段向匹配
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
redis:
# Redis 服务器主机。
host: localhost
# Redis 服务器端口。
port: 6379
jedis:
pool:
# 连接池在给定时间可以分配的最大连接数。
max-active: 8
# 连接池中空闲连接的最大数量。
max-idle: 8
# 连接池中空闲连接的最小数量。
min-idle: 0
elasticsearch:
rest:
uris: http://localhost:9200
data:
mongodb:
uri: mongodb://localhost:27017/product
4 创建实体类
产品实体类
@Entity
public class Product implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id; // 主键
private String productName; // 产品名
private Double price; // 价格
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "data_id")
private ProductData productData; //产品详情
@Transient
private List<Comment> comments = new ArrayList(); //评论
}
产品详情实体类
@Entity
public class ProductData implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id; // 主键
private String productDesc;//产品详情
}
产品 ES 实体类
@Document(indexName = "product",replicas = 2,shards = 5)
public class ProductES {
@Id
@Field(type = FieldType.Text,index = true,store = true)
private Integer id;
@Field(type = FieldType.Text,index = true,store = true,analyzer =
"ik_smart",searchAnalyzer = "ik_smart")
private String productName; // 产品名
@Field(type = FieldType.Text,index = true,store = true,analyzer =
"ik_smart",searchAnalyzer = "ik_smart")
private String productDesc;// 产品介绍
@Field(type = FieldType.Double,index = false,store = true)
private Double price;
}
评论实体类
@Document("comment")
public class Comment implements Serializable {
@Id
private Integer id; // mongodb 不能实现主键自增
private Integer pid; // 产品 id
private String username; // 评论人
private String content; // 评论内容
}
5 创建 Repository
public interface ProductRepository extends JpaRepository<Product, Integer>, JpaSpecificationExecutor<Product>
public interface ProductESRepository extends ElasticsearchRepository<ProductES,Integer>
public interface CommentRepository extends MongoRepository<Comment,Integer>
6 创建 Controller
我们设计 resultful 风格的接口:
@PostMapping("/product")
@ResponseBody
public Result saveOrUpdateProduct(@RequestBody Product product) {
return null;
}
@DeleteMapping("/product/{id}")
@ResponseBody
public Result deleteProduct(@PathVariable Integer id) {
return null;
}
@GetMapping("/product/new")
@ResponseBody
public Result newProduct() {
return null;
}
@PostMapping("/comment")
@ResponseBody
public Result saveComment(@RequestBody Comment comment) {
return null;
}
@DeleteMapping("/comment/{id}")
@ResponseBody
public Result deleteComment(@PathVariable Integer id) {
return null;
}
@GetMapping("/product/{id}")
@ResponseBody
public Result findProduct(@PathVariable Integer id) {
return null;
}
@GetMapping("/product/search")
@ResponseBody
public Result search(String keyword, @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "5") int size) {
return null;
}
7 编写 service 业务逻辑
业务逻辑较多,具体代码请参考随堂代码
8 使用 postman 工具测试接口
postman 是一款接口调试软件。我们可以用它很方便的发送任意方式的 http 请求