在项目中,门户网站展示我们提供的商品。这时,如果商品过多,就需要为普通用户提供一个搜索和查询的功能,ElasticSearch为我们提供了该服务。
1.导入jar包,创建启动类,配置application文件
<dependencies>
<!--微服务基础依赖-->
<dependency>
<groupId>com.zengjx</groupId>
<artifactId>hrm-service-dependencies</artifactId>
<version>${hrm.version}</version>
</dependency>
<!--导入elasticsearch的依赖包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<!--导入测试包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.0.5.RELEASE</version>
</dependency>
</dependencies>
//启动类 忽略Mysqlplus的一个配置类
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableEurekaClient //eureka客户端
public class SearchApp {
public static void main(String[] args) {
SpringApplication.run(SearchApp.class, args);
}
}
eureka:
client:
serviceUrl:
defaultZone: http://peer1:1010/eureka/
registry-fetch-interval-seconds: 5 #拉取注册表的时间间隔
instance:
instance-id: www.search.com:1070 #实例的ID
prefer-ip-address: true #使用IP注册到注册中心
server:
port: 1070
spring:
application:
name: service-search
data:
elasticsearch:
cluster-name: elasticsearch
cluster-nodes: 127.0.0.1:9300 #9200是图形界面端,9300代码端
2.创建一个类,该类的作用是创建索引库、文档映射、存储到ES的数据的封装
//indexName :创建索引库 type : 类型(表的类型)
@Document(indexName = "hrm",type = "course")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CourseDoc {
//设定这是主键
@Id
private Long id;
//类型为text 使用ik分词器
@Field(type = FieldType.Text,analyzer = "ik_max_word",searchAnalyzer = "ik_max_word")
private String name;
//指定为float类型
@Field(type = FieldType.Float)
private float price;
//原价
@Field(type = FieldType.Float)
private Float priceOld;
//适用人群
@Field(type = FieldType.Keyword,index = false)
private String forUser;
//课程类型
@Field(type = FieldType.Long)
private Long courseTypeId;
//等级名
@Field(type = FieldType.Keyword)
private String gradeName;
//机构
@Field(type = FieldType.Keyword)
private String tenantName;
//用来方便查询的
@Field(type = FieldType.Long)
private Long tenantId;
//图片
@Field(type = FieldType.Keyword,index = false)
private String pic;
//销量
@Field(type = FieldType.Integer)
private Integer saleCount = 0;
//浏览量
@Field(type = FieldType.Integer)
private Integer viewCount = 0;
//评论数
@Field(type = FieldType.Integer)
private Integer commentCount = 0;
//是否收费
@Field(type = FieldType.Integer)
private Integer charge;
//上线时间
@Field(type = FieldType.Date)
private Date onlineTime;
}
3.创建一个测试类用来创建索引和文档映射
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SearchApp .class)
public class ESTest {
//注入ElasticsearchTemplate
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Test
public void testCreateIndex() {
//创建索引
elasticsearchTemplate.createIndex(CourseDoc .class);
//做文档映射
elasticsearchTemplate.putMapping(CourseDoc .class);
}
}
4.创建一个接口,通过该接口来操作ElasticSearch
//该接口将交给spring管理 第一个参数为文档映射的类,第二个参数为该文档映射的主键
//这个接口为我们提供了操作elasticsearch的方法
@Repository
public interface CourseElasticsearchRepository extends ElasticsearchRepository<CourseDoc,Long> {
}
5.创建controller,其他微服务通过feign的方式调用该微服务
@RestController
public class CourseSearchController {
//提供保存和查询的方法
//注入service层中处理业务的接口
@Autowired
private ICourseElasticsearchService courseElasticsearchService;
//保存课程
@RequestMapping(value = "/search/course/save",method = RequestMethod.POST)
public AjaxResult saveCourse(@RequestBody CourseDoc doc ){
courseElasticsearchService.save(doc);
return AjaxResult.me();
}
//使用ES课程查询并返回给前端一个查询后的数据集合
@RequestMapping(value = "/es/searchCourse",method = RequestMethod.POST)
public AjaxResult searchCourse(@RequestBody CourseQuery courseQuery ){
PageList pageList = courseElasticsearchService.searchCourse(courseQuery);
return AjaxResult.me().setResultObj(pageList);
}
}
6.创建service层,保存数据到ElasticSearch和在ElasticaSearch中通过传入的条件查询数据
@Service
public class CourseElasticsearchServiceImpl implements ICourseElasticsearchService{
//注入ElasticSearch的
@Autowired
private CourseElasticsearchRepository repository;
//执行保存 保存到ElasticSeach的索引库中
@Override
public void save(CourseDoc doc) {
repository.save(doc);
}
//使用ES课程查询并返回给前端一个查询后的数据集合
@Override
public PageList searchCourse(CourseQuery courseQuery) {
//创建一个本地的查询器
NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
//通过传入对象的信息来设置排序
//前端通过四种字段来排序
//销量 价格 评论 人气
//先判断是否为空
if(StringUtils.isNotEmpty(courseQuery.getSortField())){
//设置一个字符串常量用来作为参数 默认使用上架时间作为排序字段
String sortFiled = "onlineTime";
//当字段不为空的时候 使用switch循环的方式
switch (courseQuery.getSortField().toLowerCase()){
case "xl" : sortFiled = "saleCount"; break;
case "jp" : sortFiled = "price"; break;
case "pl" : sortFiled = "commentCount"; break;
case "rq" : sortFiled = "viewCount"; break;
}
//排序方式 默认使用DESC方式排序
SortOrder sort = SortOrder.DESC;
//当sortType不为空,且传入的是ASC的时候才使用SortOrder.ASC的方式排序
if (StringUtils.isNotEmpty(courseQuery.getSortType()) && courseQuery.getSortType().equalsIgnoreCase("asc")){
sort = SortOrder.ASC;
}
//将排序的方式交给本地查询器 第一个参数为哪一个字段作为查询 第二个参数为查询方式
builder.withSort(SortBuilders.fieldSort(sortFiled).order(sort));
}
//=====================================================================================
//通过传入参数来分页 使用的是pageRequest中的of方法来进行分页 第一个参数为多少页开始(0表示第一页) 第二个参数为每页条数
builder.withPageable(PageRequest.of(courseQuery.getPage() - 1,courseQuery.getRows()));
//=====================================================================================
//使用组合查询 获取到组合查询器
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//使用组合查询器查询课程
//判断课程是否为空 前端传入到后台为keyword我们通过这个字符串来查询课程
if (StringUtils.isNotEmpty(courseQuery.getKeyword())){
//使用组合查询器中must方式 通过QueryBuilders中的matchQuery方法查询(分词的方式) 第一个参数为数据的哪一个字段,第二个参数为传入的查询条件
boolQueryBuilder.must(QueryBuilders.matchQuery("name",courseQuery.getKeyword()));
}
//使用组合查询课程分类
if (courseQuery.getCourseTypeId() != null){
//使用组合查询中的filter方式 通过QueryBuilders中的mtermQuery方法查询 第一个参数为数据字段 第二个参数为匹配字段的数据 这是精准查询相当于==
boolQueryBuilder.filter(QueryBuilders.termQuery("courseTypeId",courseQuery.getCourseTypeId()));
}
//使用组合查询课程等级
if (StringUtils.isNotEmpty(courseQuery.getGradeName())){
//使用组合查询中的filter方式 通过QueryBuilders中的mtermQuery方法查询 第一个参数为数据字段 第二个参数为匹配字段的数据
boolQueryBuilder.filter(QueryBuilders.termQuery("gradeName",courseQuery.getGradeName()));
}
//使用组合查询查询最小价格
if (courseQuery.getPriceMin() != null){
//使用组合查询中的filter方式 通过QueryBuilders中的mtermQuery方法查询 第一个参数为数据字段 get中传入最小价格
boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(courseQuery.getPriceMin()));
}
//使用组合查询查询最大价格
if (courseQuery.getPriceMax() != null){
//使用组合查询中的filter方式 通过QueryBuilders中的mtermQuery方法查询 第一个参数为数据字段 get中传入最小价格
boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").lte(courseQuery.getPriceMax()));
}
//使用组合查询查询机构名称
if (StringUtils.isNotEmpty(courseQuery.getTenantName())){
//使用组合查询中的filter方式
boolQueryBuilder.filter(QueryBuilders.termQuery("tenantName",courseQuery.getTenantName()));
}
//=====================================================================================
//将查询器交给本地查询器
builder.withQuery(boolQueryBuilder);
//使用本地查询器在ES中查询
Page<CourseDoc> search = repository.search(builder.build());
//把查询结果封装为PageList 第一个参数为所有的数据(为一个几个) 第二个参数为数据总条数
return new PageList(search.getTotalElements() , search.getContent());
}
}
本文介绍如何在项目中集成ElasticSearch进行商品搜索功能的开发,包括导入依赖、创建索引库、实现搜索接口等关键步骤。

2万+

被折叠的 条评论
为什么被折叠?



