畅购07,08—— 商品搜索模块(ElasticSearch)

商品搜索分为三大模块

1 数据同步ES

1.1 ElasticSearch全文检索

  • 面试题:
  1. 百度,淘宝为什么查询快?
    都采用了ES全文检索技术。
  2. 全文检索技术,查询快的原因?
    ES使用倒排索引,对搜索内容进行分词,一个词对应多个id。当然,生成的倒排索引中,词条会排序,形成一颗树形结构,提升词条的查询速度。输入关键词之后就会很快的根据分词找到对应的id便于查到数据。
  3. 为什么有了mysql关系数据库,还需要引入ES?
    性能低,功能弱,例如:模糊查询时不走索引会极其的慢。

1.2 商品上下架同步到ES

实现思路
  1. canal微服务监听tb_spu表,当上架(is_marketable变为1),拿到spuId根据routingKey分发消息给绑定的queue。
  2. search微服务监听此queue,拿到spuId,业务层里feign调用拿到对应的skuList,同步ES数据
具体操作
  • canal模块中:发送消息到mq,只要tb_spu表发生改变,就有消息
  • search模块中:
  1. 引入goods_api(当中创建了索引结构,实体类skuInfo中加各个注解
  2. 配置yml
  3. 定义一个ESManagerMapper继承ElasticsearchRepository<SkuInfo,Long>
  4. 编写监听类,拿到spuId调用业务层
  5. 通过elasticsearchTemplate根据SkuInfo创建ES的索引和映射
  6. 业务层feign调用拿到skuList,先转成字符串再转成对应的List<SkuInfo>(这个设计非常巧妙,因为sku和skuInfo的字段相同,但属性不一,通过JSON转换一下即可),遍历每个skuInfo,将规格spec转成specMap,最后调用saveAll方法将所有的上架商品同步到ES。
  • 代码如下:
public void importDataTemp(String spuId) {
   
        //通过远程调用根据spuId查询所有sku
        List<Sku> skuList = skuFeign.findSkuListBySpuId(spuId);
        if (skuList==null||skuList.size()<=0){
   
                throw new BusinessException(new Result(false, StatusCode.REMOTEERROR,"未查到相关Sku信息"));
            }
            //数据库对应的sku和es对应的skuInfo字段一样,类型不一样,转成json再转成集合
            String jsonString = JSON.toJSONString(skuList);
            List<SkuInfo> skuInfos = JSON.parseArray(jsonString, SkuInfo.class);
            for (SkuInfo skuInfo : skuInfos) {
   
                //将规格信息转换为map
                Map specMap = JSON.parseObject(skuInfo.getSpec(), Map.class);
                skuInfo.setSpecMap(specMap);
        }
        esManagerMapper.saveAll(skuInfos);
    }
  • 下架操作雷同上架
    先通过spuId拿到sku集合,最后遍历删除esManagerMapper.deleteById(Long.parseLong(sku.getId()));

2 商品搜索条件封装

2.1 基本分为6个条件

  • 根据搜索关键字查询
  • 规格过滤
  • 价格区间搜索
  • 分页查询
  • 排序查询
  • 高亮查询

2.2 步骤

  • 创建接口
 public interface SearchService {
   
    /**
     * 全文检索
     * @param paramMap  查询参数
     * @return
     */
    public Map search(Map<String, String> paramMap) throws Exception;
}
  • 实现方法
  1. 构造查询条件封装对象new NativeSearchQueryBuilder()
  2. 组合查询条件使用BoolQuery
  3. 关键字查询:must连接方式,使用matchQuery(ik分词器进行分词),指定es中的字段和map中的keywords对应
  4. 品牌和规格聚合:addAggregation
  5. 品牌过滤:filter连接方式,使用teamQuery,指定es中的brandName和map中的brand对应
  6. 规格过滤:filter连接方式,使用teamQuery
  7. 价格区间过滤:filter连接方式,使用rangeQuery(lte小于,gte大于)
  8. 分页过滤:withPageable
  9. 价格过滤:withSort
  10. 高亮过滤:withHighlightFields
  11. 调用elasticsearchTemplate的queryForPage
  12. 最后将结果一一封装到返回的结果集(resultMap中)
  • 代码:
 @Override
    public Map search(Map<String, String> searchMap) {
   
        Map<String, Object> resultMap = new HashMap<>();
        //判断搜索条件不为空
        if (searchMap != null && searchMap.size()>0) {
   
            //查询对象构建器
            NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值