基于Spring Data Elasticsearch的搜索微服务

本文详细介绍了如何使用Spring Data Elasticsearch构建一个搜索微服务,包括数据导入、基本搜索实现、搜索过滤、优化等步骤。重点讲解了FeignClient的使用、商品数据结构设计、分页和排序功能、过滤条件的生成和筛选,以及针对性能的优化策略。
摘要由CSDN通过智能技术生成


数据导入

module: leyou-search

数据结构

我们创建一个类,封装要保存到索引库的数据,并设置映射属性:

@Document(indexName = "goods", type = "docs", shards = 1, replicas = 0)
//索引库goods 表名docs 分1片  0副本
public class Goods {
   
    @Id
    private Long id; // spuId
    //String 两种选择:Text,Keyword  +@Field
    @Field(type = FieldType.Text, analyzer = "ik_max_word")//Text分词
    private String all; // 所有需要被搜索的信息,包含标题,分类,甚至品牌
    @Field(type = FieldType.Keyword, index = false)
    private String subTitle;// 卖点
    private Long brandId;// 品牌id
    private Long cid1;// 1级分类id
    private Long cid2;// 2级分类id
    private Long cid3;// 3级分类id
    private Date createTime;// 创建时间
    private List<Long> price;// 价格
    @Field(type = FieldType.Keyword, index = false)
    private String skus;// List<sku>信息的json结构
    private Map<String, Object> specs;// 可搜索的规格参数,key是参数名,值是参数值
}

商品微服务提供接口

索引库中的数据来自于数据库,我们不能直接去查询商品的数据库,因为真实开发中,每个微服务都是相互独立的,包括数据库也是一样。所以我们只能调用商品微服务提供的接口服务。

先思考我们需要的数据:

  • SPU信息
  • SKU信息
  • SPU的详情
  • 商品分类名称(拼接all字段)
  • 品牌名称
  • 规格参数

再思考我们需要哪些服务:

  • 第一:分批查询spu的服务,已经写过。
  • 第二:根据spuId查询sku的服务,已经写过
  • 第三:根据spuId查询SpuDetail的服务,已经写过
  • 第四:根据商品分类id,查询商品分类名称,没写过
  • 第五:根据商品品牌id,查询商品的品牌,没写过
  • 第六:规格参数接口

因此我们需要额外提供(在CategoryController中)查询商品分类名称的接口。

FeignClient

第一步:服务的提供方在leyou-item-interface中提供API接口,并编写接口声明:

  • 我们的服务提供方不仅提供实体类,还要提供api接口声明
  • 调用方不用自己编写接口方法声明,直接继承提供方给的Api接口即可,
    在这里插入图片描述

需要引入springMVC及leyou-common的依赖:

第二步:在调用方leyou-search中编写FeignClient,但不要写方法声明了,直接继承leyou-item-interface提供的api接口:

在这里插入图片描述

测试

在leyou-search中引入springtest依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

创建测试类:

在接口上按快捷键:Ctrl + Shift + T

在这里插入图片描述

测试代码:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = LeyouSearchApplication.class)
public class CategoryClientTest {
   

    @Autowired
    private CategoryClient categoryClient;

    @Test
    public void testQueryCategories() {
   
        List<String> names = this.categoryClient.queryNamesByIds(Arrays.asList(1L, 2L, 3L));
        names.forEach(System.out::println);
    }
}

在这里插入图片描述

导入数据

在这里插入图片描述
在这里插入图片描述

乐优商城(十七)——搜索微服务(数据导入修改)

实现基本搜索

当我们输入任何文本,点击搜索,就会跳转到搜索页search.html了:

并且将搜索关键字以请求参数携带过来:
在这里插入图片描述

后台提供搜索接口

在leyou-gateway中的CORS配置类中,添加允许信任域名:
在这里插入图片描述
并在leyou-gateway工程的Application.yml中添加网关映射:
在这里插入图片描述
在这里插入图片描述

首先分析几个问题:

  • 请求方式:Post

  • 请求路径:/search/page,不过前面的/search应该是网关的映射路径,因此真实映射路径page,代表分页查询

  • 请求参数:json格式,目前只有一个属性:key-搜索关键字,但是搜索结果页一定是带有分页查询的,所以将来肯定会有page属性,因此我们可以用一个对象来接收请求的json数据:

    public class SearchRequest {
         
        private String key;// 搜索条件
    
        private Integer page;// 当前页
    
        private static final Integer DEFAULT_SIZE = 20;// 每页大小,不从页面接收,而是固定大小
        private static final Integer DEFAULT_PAGE = 1;// 默认页
    
        public String getKey() {
         
            return key;
        }
    
        public void setKey(String key) {
         
            this.key = key;
        }
    
        public Integer getPage() {
         
            if(page == null){
         
                return DEFAULT_PAGE;
            }
            // 获取页码时做一些校验,不能小于1
            return Math.max(DEFAULT_PAGE, page);
        }
    
        public void setPage(Integer page) {
         
            this.page = page;
        }
    
        public Integer getSize() {
         
            return DEFAULT_SIZE;
        }
    }
    
  • 返回结果:作为分页结果,一般都两个属性:当前页数据、总条数信息,我们可以使用之前定义的PageResult类

代码:

@RestController
@RequestMapping
public class SearchController {
   

    @Autowired
    private SearchService searchService;

    /**
     * 搜索商品
     *
     * @param request
     * @return
     */
    @PostMapping("page")
    public ResponseEntity<PageResult<Goods>> search(@RequestBody SearchRequest request) {
   
        PageResult<Goods> result = this.searchService.search(request);
        if (result == null) {
   
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
        return ResponseEntity.ok(result);
    }
}

service

@Service
public class SearchService {
   

    @Autowired
    private GoodsRepository goodsRepository;

    public PageResult<Goods> search(SearchRequest request) {
   
        String key 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值