SpringCloud——ElasticSearch的使用

本文介绍如何在项目中集成ElasticSearch进行商品搜索功能的开发,包括导入依赖、创建索引库、实现搜索接口等关键步骤。

在项目中,门户网站展示我们提供的商品。这时,如果商品过多,就需要为普通用户提供一个搜索和查询的功能,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());
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值