1. 什么是Spring Data ElasticSearch
Spring Data Elasticsearch是Spring Data项目下的一个子模块。
查看 Spring Data的官网:http://projects.spring.io/spring-data/
Spring Data ElasticSearch 基于 spring data API 简化 elasticSearch操作,将原始操作elasticSearch的客户端API 进行封装 。Spring Data为Elasticsearch项目提供集成搜索引擎。Spring Data Elasticsearch POJO的关键功能区域为中心的模型与Elastichsearch交互文档和轻松地编写一个存储库数据访问层。
官方网站:http://projects.spring.io/spring-data-elasticsearch
###1.SpringData ES说明
在后期项目开发中,XML整合方式已经落伍了,目前市面上的项目都是拥抱SpringBoot框架,来实现项目的构建,那么课程就使用SpringBoot完成Spring Data ES的整合。就不用管传统applicationContext.xml整合方式
2.SpringData ES整合步骤
2.1.准备搜索的服务工程
<?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">
<parent>
<artifactId>easygo</artifactId>
<groupId>com.bruce.easygo</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>easygo-search-service</artifactId>
<!--导入项目中的依赖-->
<dependencies>
<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>com.bruce.easygo</groupId>
<artifactId>easygo-pojo</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<!-- Eureka客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>com.bruce.easygo</groupId>
<artifactId>easygo-commons</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
server.port=9009
# 配置Eureka信息
# 服务的名字,注册到注册中心的名字,后期消费者来根据名字调用服务 可以重复
spring.application.name=easygo-search-service
# EurekaServer地址
eureka.client.service-url.defaultZone=http://127.0.0.1:9001/eureka
# 当调用getHostname获取实例的hostname时,返回ip而不是host名称
eureka.instance.prefer-ip-address=true
# 指定自己的ip信息,不指定的话会自己寻找
eureka.instance.ip-address=127.0.0.1
# 执行当前服务的应用ID 不可以重复 标识的是每一个具体的的服务
eureka.instance.instance-id=easygo-search-service-9009
2.2.项目中引入依赖
<!--导入Spring Data ES依赖-->
<!--spring-data elasticsearch-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
2.3.配置Spring Data ES的配置信息
# Spring Data elasticsearch配置
spring.data.elasticsearch.cluster-name=elasticsearch
# 连接地址
spring.data.elasticsearch.cluster-nodes=127.0.0.1:9300
#设置连接超时时间
spring.data.elasticsearch.properties.transport.tcp.connect_timeout=120s
2.4.测试ES的连接
package com.easygo.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
/**
* @BelongsProject: easygo
* @BelongsPackage: com.easygo.test
* @Author: bruceliu
* @QQ:1241488705
* @CreateTime: 2020-04-10 15:20
* @Description: TODO
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestES {
//如果要操作Redis,需要获取一个 RedisTemplate
//如果要操作ES,需要获取 ElasticsearchTemplate,天下我有!
@Resource
ElasticsearchTemplate elasticsearchTemplate;
/**
* 01-测试工具类
*/
@Test
public void testConn(){
System.out.println("ES操作的工具类:"+elasticsearchTemplate);
}
/**
*02-创建一个索引库? Goods索引库,实际的项目搜索的是商品数据!
*/
@Test
public void testCreateIndex(){
//创建索库
elasticsearchTemplate.createIndex("goodsindexs");
System.out.println("测试创建索引库");
}
}
3.使用面向对象思想创建索引库和Mapping
3.1.准备一个实体类,索引库对应
package com.easygo.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @BelongsProject: easygo
* @BelongsPackage: com.easygo.pojo
* @Author: bruceliu
* @QQ:1241488705
* @CreateTime: 2020-04-10 15:55
* @Description: 商品实体类
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Goods implements Serializable {
private static final long serialVersionUID = 8972263575352384971L;
private Integer id;
private String seller_id; //卖家ID
private String goods_name; //商品的标题
private Integer default_item_id; //默认上架商品ID
private String audit_status; //当前状态
private String is_marketable; //是否上架
private Integer brand_id; //商品的品牌ID
private String caption; //商品的副标题
private Integer category1_id;
private Integer category2_id;
private Integer category3_id;
private String small_pic; //商品的小图
private Double price; //商品的价格
private Integer type_template_id;
private String is_enable_spec;
private String is_delete;
}
3.2. 给实体类加一些注解(Spring Data ES注解),配置Mapping规则的注解
<!--导入Spring Data ES依赖 把它导入到实体类中-->
<!--spring-data elasticsearch-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
package com.easygo.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import java.io.Serializable;
/**
* @BelongsProject: easygo
* @BelongsPackage: com.easygo.pojo
* @Author: bruceliu
* @QQ:1241488705
* @CreateTime: 2020-04-10 15:55
* @Description: 商品实体类
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
//文档对象是(索引库名,类型)
@Document(indexName = "goodsindex",type = "goods")
public class Goods implements Serializable {
private static final long serialVersionUID = 8972263575352384971L;
//字段的配置 类型 是否索引 是否存储
@Field(store = true,index = false,type = FieldType.Integer)
private Integer id;
private String seller_id; //卖家ID
@Field(store = true,analyzer = "ik_max_word",index = true,searchAnalyzer ="ik_max_word",type = FieldType.Text)
private String goods_name; //商品的标题
private Integer default_item_id; //默认上架商品ID
private String audit_status; //当前状态
private String is_marketable; //是否上架
@Field(store = true,index = false,type = FieldType.Integer)
private Integer brand_id; //商品的品牌ID
@Field(store = true,analyzer = "ik_max_word",index = true,searchAnalyzer ="ik_max_word",type = FieldType.Text)
private String caption; //商品的副标题
private Integer category1_id;
private Integer category2_id;
private Integer category3_id;
@Field(store = true,index = false,type = FieldType.Text)
private String small_pic; //商品的小图
@Field(store = true,index = false,type = FieldType.Double)
private Double price; //商品的价格
private Integer type_template_id;
private String is_enable_spec;
private String is_delete;
}
package com.easygo.test;
import com.easygo.client.GoodsClient;
import com.easygo.pojo.Goods;
import com.easygo.service.GoodsService;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @BelongsProject: easygo
* @BelongsPackage: com.easygo.test
* @Author: bruceliu
* @QQ:1241488705
* @CreateTime: 2020-04-10 15:20
* @Description: TODO
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestES {
//如果要操作Redis,需要获取一个 RedisTemplate
//如果要操作ES,需要获取 ElasticsearchTemplate,天下我有!
@Resource
ElasticsearchTemplate elasticsearchTemplate;
@Resource
GoodsClient goodsClient;
@Autowired
GoodsService goodsService;
/**
* 01-测试工具类
*/
@Test
public void testConn(){
System.out.println("ES操作的工具类:"+elasticsearchTemplate);
}
/**
*02-创建一个索引库? Goods索引库,实际的项目搜索的是商品数据!
*/
@Test
public void testCreateIndex(){
//创建索库,索引库的名字是??
elasticsearchTemplate.createIndex(Goods.class);
System.out.println("测试创建索引库成功~");
elasticsearchTemplate.putMapping(Goods.class);//因为类上面有注解
System.out.println("创建Goods的Mapping完成");
}
/**
* 新增数据库中的数据到ES索引库中
*/
@Test
public void testAddDocument(){
List<Goods> goodsList = goodsClient.getGoods(1);
for (Goods goods : goodsList) {
System.out.println("正在导入:"+goods);
}
goodsService.saveDocuments(goodsList);
System.out.println("批量新增索引库数据成功......");
}
/**
* 根据ID查询
*/
@Test
public void testgetDocumentById(){
Goods goods = goodsService.getDocumentById(149187842868047L);
System.out.println("查询的对象是:"+goods);
}
/**
* 根据ID更新
*/
@Test
public void testUpdateById(){
Goods goods = goodsService.getDocumentById(149187842867986L);
System.out.println("查询的原对象是:"+goods);
goods.setGoods_name("阿玛尼装逼神器");
goods.setCaption("阿玛尼装逼神器,泡妞必备,值得哟拥有");
goods.setPrice(250.0);
goodsService.updateDocumentById(goods);
System.out.println("更新document");
}
/**
* 根据ID删除
*/
@Test
public void testDeleteByid(){
goodsService.deleteDocumentById(149187842867914L);
System.out.println("删除成功");
}
/**
* 删除所有
*/
@Test
public void testDeleteAll(){
goodsService.deleteAllDocument();
System.out.println("全部干光了");
}
/**
* 测试关键词查询01 条件查询分页
*/
@Test
public void testQuery1(){
int pageIndex=4; //当前页码
int pageSize=3; //页码大小
String keywords="手机"; //用户输入的关键词
//构建一个查询对象
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
//设置查询条件,可以构建多个条件
.withQuery(QueryBuilders.queryStringQuery(keywords).defaultField("goods_name"))
//设置分页的信息,页码从0开始计算
.withPageable(PageRequest.of(pageIndex - 1, pageSize)).build();
//条件查询分页,返回分页对象
AggregatedPage<Goods> page = elasticsearchTemplate.queryForPage(searchQuery, Goods.class);
System.out.println("当前页码:"+pageIndex);
System.out.println("页面大小:"+pageSize);
System.out.println("总页数:"+page.getTotalPages());
System.out.println("总条数:"+page.getTotalElements());
System.out.println("每页到的数据是:");
List<Goods> goodsList = page.getContent();
for (Goods goods : goodsList) {
System.out.println(goods);
}
}
/**
* 多条件搜索 分页
*/
@Test
public void testtestQuery2(){
int pageIndex=1; //当前页码
int pageSize=3; //页码大小
String keywords="火爆"; //用户输入的关键词
NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
if(keywords!=null&&!"".equals(keywords)){
builder.withQuery(QueryBuilders.multiMatchQuery(keywords, "goods_name", "caption"));
}
//设置分页的信息,页码从0开始计算
builder.withPageable(PageRequest.of(pageIndex - 1, pageSize));
NativeSearchQuery searchQuery = builder.build();
//条件查询分页,返回分页对象
AggregatedPage<Goods> page = elasticsearchTemplate.queryForPage(searchQuery, Goods.class);
System.out.println("当前页码:"+pageIndex);
System.out.println("页面大小:"+pageSize);
System.out.println("总页数:"+page.getTotalPages());
System.out.println("总条数:"+page.getTotalElements());
System.out.println("每页到的数据是:");
List<Goods> goodsList = page.getContent();
for (Goods goods : goodsList) {
System.out.println(goods);
}
}