SpringBoot整合Elasticsearch-Rest-Client实战


前言

Elasticsearch搜索引擎整合SpringBoot,官方的RestClient,封装了ES操作,API层次分明,上手简单。此处为Elasticsearch-Rest-Client在实际项目中的一种应用。

本文章建立在Elasticsearch-Rest-Client整合springboot的前提下

Elasticsearch-Rest-Client整合springboot


 
 

一、feign服务调用(cloud使用,boot项目直接忽略)

此处搜索引擎的搜索对象为商品,在SpringCloud中需使用服务调用来调用商品模块的方法

1.引入依赖

service模块中引入依赖

<!--服务调用-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

 

2.调用方增加注解

service_search模块启动类上增加注解

import org.springframework.cloud.openfeign.EnableFeignClients;
​
@EnableFeignClients

6eda8b5a94d342f48bdbb6d3c59a7efc.png

 

3.调用端-创建调用接口

package com.ly.search.client;
import com.ly.commonutils.R;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
​
@FeignClient(name = "service-shop")
public interface UserClient {
    @GetMapping("/shopservice/clothes/allGoods") //所有商品信息
    public R AllGoods();
}

二、使用步骤

1.创建搜索的对象类

//商品搜索实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Clothes implements Serializable {
    @ApiModelProperty(value = "衣服id")
    private String id;

    @ApiModelProperty(value = "店铺id")
    private String businessId;

    @ApiModelProperty(value = "标题")
    private String title;

    @ApiModelProperty(value = "图片")
    private String photo;

    @ApiModelProperty(value = "价格")
    private BigDecimal price;

    @ApiModelProperty(value = "销售数量")
    private Long buyCount;

    @ApiModelProperty(value = "浏览次数")
    private Long viewCount;

    @ApiModelProperty(value = "类型")
    private String type;

    @ApiModelProperty(value = "状态,0:已下架,1:已上架,2:审核中,3:违规未通过")
    private Integer status;
}

2.编写service及其实现类

service:

public interface SearchService {
    //获取索引内容
    List<Clothes> getIndex(String string);

    //Api方式创建索引及其数据
     void getByApi();

     //定时更新索引
     void task();
}

实现类:

        实现类加上@EnableScheduling注解开启定时任务

@Service
@EnableScheduling //开启定时任务
public class SeachServiceImpl implements SearchService {

         添加索引及定时更新索引,使用服务调用,将商品模块的方法获得的数据作为索引数据

@Autowired
    private RestHighLevelClient client;

    @Autowired
    private UserClient userClient; //商品模块调用接口

    @PostConstruct //Spring启动后对象自动注入完成后执行
    @Override
    public void getByApi() {
        //获取消息R中的数据
        R info=userClient.AllGoods();
        Map<String, Object> map=info.getData();

        //此处编译通过,但集合遍历报java.util.LinkedHashMap cannot be cast to xxx数据转换异常错误
       List<Clothes> list= (List<Clothes>) map.get("items");

        //可利用alibaba的fastjson工具包先将数据转换为json格式,再转为我们需要的格式
        String jsonString=JSON.toJSONString(list);
        List<Clothes> datas=JSONObject.parseArray(jsonString,Clothes.class);
        datas.forEach(System.out::println);

        //1.创建索引
        IndexRequest indexRequest=new IndexRequest("goods");
        int i=0;
        //2.执行操作
        for (Clothes clothes:datas) {
            i+=1;
            indexRequest.id(String.valueOf(i));
            indexRequest.type("clothes");
            String json=JSON.toJSONString(clothes);
            indexRequest.source(json, XContentType.JSON);//要保存的内容
            IndexResponse index = null;
            try {
                index = client.index(indexRequest, ElasticSearchConfig.COMMON_OPTIONS);
                System.out.println("数据添加成功");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    @Scheduled(fixedRate = 1000*60) //一分钟执行一次
    public void task() {
        //删除索引
            DeleteIndexRequest indexRequest=new DeleteIndexRequest("goods");
            try {
                client.indices().delete(indexRequest,ElasticSearchConfig.COMMON_OPTIONS);
                System.out.println("索引删除成功");
            } catch (IOException e) {
                e.printStackTrace();
            }
            //执行创建索引方法
            this.getByApi();
        System.err.println("执行更新索引定时任务时间: " + LocalDateTime.now());
    }

         搜索方法的实现

@Override
    public List<Clothes> getIndex(String str)  {
        //1.创建检索请求
        SearchRequest searchRequest=new SearchRequest();
        //指定索引
        searchRequest.indices("shops");
        //指定DSL,检索条件
        SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
        //1.1构造检索条件,使用matchPhrase对查询内容str整体匹配
        sourceBuilder.query(QueryBuilders.matchPhraseQuery("title",str));
        //ES折叠,根据字段数据去重,此处类型必须为keyword
        sourceBuilder.collapse(new CollapseBuilder("id.keyword"));
        searchRequest.source(sourceBuilder);

        //2.创建搜索实体类集合接收数据
        List<Clothes> list=new ArrayList<Clothes>();

        //3.执行索引
        SearchResponse searchResponse=null;
        try {
             searchResponse=client.search(searchRequest, ElasticSearchConfig.COMMON_OPTIONS);

            //4.获取所有查到的数据
            SearchHits hits=searchResponse.getHits();
            SearchHit[] searchHits=hits.getHits();

            //5.转换为搜索实体类数据
            for (SearchHit hit:searchHits
                 ) {
                String string=hit.getSourceAsString();
                  Clothes clothes=JSON.parseObject(string, Clothes.class);
                  list.add(clothes);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        return list;
    }

 

 controller类:

@RestController
@CrossOrigin
@RequestMapping("searchservice")
public class SearchController {
    @Autowired
    private SearchService searchService;

    @ApiOperation("商品搜索")
    @PostMapping("search/{string}")
    public R search(
            @ApiParam(name = "string",value = "搜索内容",required = true)
            @PathVariable String string
    ){
        if(string!=null &&string!="") {
            List<Clothes> list = searchService.getIndex(string);
            return R.ok().data("items", list);
        }else{
            return R.error();
        }
    }
 }

 

总结

1.索引的创建与删除不能经过controller,经过的话意味着用户的每请求一次就要重新创建索引、删除索引;而在高并发情况下,多个用户同时请求也会造成同时间创建(或删除)大量索引,导致Elasticsearch客户端宕机。

2.为了保证索引的数据正确性,设置定时任务,定时更新索引,且更新间隔不应太长。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lycirsp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值