当前位置: 首页 > article >正文

电商项目-基于ElasticSearch实现商品搜索功能(一)

一、根据关键字查询商品

(1) shangcheng_service_search项目创建SearchService接口

public interface SearchService {/**
     * 全文检索
     * @param paramMap  查询参数
     * @return
     */
    public Map search(Map<String, String> paramMap) throws Exception;
}

(2) shangcheng_service_search项目创建SearchService接口实现类SearchServiceImpl

@Service
public class SearchServiceImpl implements SearchService {@Autowired
    private ElasticsearchTemplate esTemplate;
​
​
​
    //设置每页查询条数据
    public final static Integer PAGE_SIZE = 20;@Override
    public Map search(Map<String, String> searchMap) throws Exception {
        Map<String, Object> resultMap = new HashMap<>();//有条件才查询Es
        if (null != searchMap) {
            //组合条件对象
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
            //0:关键词
            if (!StringUtils.isEmpty(searchMap.get("keywords"))) {
                boolQuery.must(QueryBuilders.matchQuery("name", searchMap.get("keywords")).operator(Operator.AND));
               
            }//4. 原生搜索实现类
            NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
            nativeSearchQueryBuilder.withQuery(boolQuery);
            
            //10: 执行查询, 返回结果对象
            AggregatedPage<SkuInfo> aggregatedPage = esTemplate.queryForPage(nativeSearchQueryBuilder.build(), SkuInfo.class, new SearchResultMapper() {
                @Override
                public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) {List<T> list = new ArrayList<>();SearchHits hits = searchResponse.getHits();
                    if (null != hits) {
                        for (SearchHit hit : hits) {
                            SkuInfo skuInfo = JSON.parseObject(hit.getSourceAsString(), SkuInfo.class);
​
                            list.add((T) skuInfo);
                        }
                    }
                    return new AggregatedPageImpl<T>(list, pageable, hits.getTotalHits(), searchResponse.getAggregations());
                }
            });//11. 总条数
            resultMap.put("total", aggregatedPage.getTotalElements());
            //12. 总页数
            resultMap.put("totalPages", aggregatedPage.getTotalPages());
            //13. 查询结果集合
            resultMap.put("rows", aggregatedPage.getContent());return resultMap;
        }
        return null;
    }}

(3) shangcheng_service_search项目创建SearchController

@RestController
@RequestMapping("/sku_search")
public class SearchController {@Autowired
    private EsManagerService esManagerService;@Autowired
    private SearchService searchService;
    
     //对搜索入参带有特殊符号进行处理
    public void handlerSearchMap(Map<String,String> searchMap){if(null != searchMap){
            Set<Map.Entry<String, String>> entries = searchMap.entrySet();
            for (Map.Entry<String, String> entry : entries) {
                if(entry.getKey().startsWith("spec_")){
                    searchMap.put(entry.getKey(),entry.getValue().replace("+","%2B"));
                }
            }
        }}/**
     * 全文检索
     * @return
     */
    @GetMapping
    public Map search(@RequestParam Map<String, String> paramMap) throws Exception {
        //特殊符号处理
        handlerSearchMap(searchMap);
        Map resultMap = searchService.search(paramMap);
        return resultMap;
    }
}

(4) 测试

使用postmain访问 http://localhost:9009/sku_search?keywords=手机

二、品牌筛选

用户有可能会根据分类搜索、品牌搜索,还有可能根据规格搜索,以及价格搜索和排序操作。根据分类和品牌搜索的时候,可以直接根据指定域搜索,而规格搜索的域数据是不确定的,价格是一个区间搜索,所以我们可以先实现分类、品牌搜素,再实现规格搜索,然后实现价格区间搜索。

2.1 需求分析

页面每次向后台传入对应的分类和品牌,后台据分类和品牌进行条件过滤。

2.2 代码实现

修改搜索微服务com.shangcheng.service.SearchServiceImpl的搜索方法,添加品牌过滤,代码如下:

代码如下:

@Override
public Map search(Map<String, String> searchMap) throws Exception {
    Map<String, Object> resultMap = new HashMap<>();//有条件才查询Es
    if (null != searchMap) {
        //组合条件对象
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //0:关键词
        if (StringUtils.isNotEmpty(searchMap.get("keywords"))) {
            boolQuery.must(QueryBuilders.matchQuery("name", searchMap.get("keywords")).operator(Operator.AND));
        }
        //1:条件 品牌
        if (StringUtils.isNotEmpty(searchMap.get("brand"))) {
            boolQuery.filter(QueryBuilders.termQuery("brandName", searchMap.get("brand")));
        }
        
        //4. 原生搜索实现类
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(boolQuery);//6. 品牌聚合(分组)查询
        String skuBrand = "skuBrand";
nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms(skuBrand).field("brandName"));//10: 执行查询, 返回结果对象
        AggregatedPage<SkuInfo> aggregatedPage = esTemplate.queryForPage(nativeSearchQueryBuilder.build(), SkuInfo.class, new SearchResultMapper() {
            @Override
            public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) {List<T> list = new ArrayList<>();SearchHits hits = searchResponse.getHits();
                if (null != hits) {
                    for (SearchHit hit : hits) {
                        SkuInfo skuInfo = JSON.parseObject(hit.getSourceAsString(), SkuInfo.class);
​
                        list.add((T) skuInfo);
                    }
                }
                return new AggregatedPageImpl<T>(list, pageable, hits.getTotalHits(), searchResponse.getAggregations());
            }
        });//11. 总条数
        resultMap.put("total", aggregatedPage.getTotalElements());
        //12. 总页数
        resultMap.put("totalPages", aggregatedPage.getTotalPages());
        //13. 查询结果集合
        resultMap.put("rows", aggregatedPage.getContent());//14. 获取品牌聚合结果
        StringTerms brandTerms = (StringTerms) aggregatedPage.getAggregation(skuBrand);
        List<String> brandList = brandTerms.getBuckets().stream().map(bucket -> bucket.getKeyAsString()).collect(Collectors.toList());
        resultMap.put("brandList", brandList);return resultMap;
    }
    return null;
}
 

2.3 测试

测试:

访问地址:http://localhost:9009/sku_search?keywords=手机


http://www.kler.cn/a/467932.html

相关文章:

  • 实际开发中,常见pdf|word|excel等文件的预览和下载
  • 谷歌浏览器的书签同步功能详解
  • MySQL的三大日志
  • Linux 基础 4.文件IO 通用的IO模型
  • 深度学习中的步数指的是什么
  • AngularJS HTML DOM
  • 2025-01-04 Unity插件 YodaSheet1 —— 插件介绍
  • 【深度学习入门_基础篇】线性代数本质
  • 进军AI大模型-Langchain程序部署
  • DS复习提纲模版
  • asp.net core 发布到iis后,一直500.19,IIS设置没问题,安装了sdk,文件夹权限都有,还是报错
  • RestClient操作Elasticsearch
  • 【Java】集合中的List【主线学习笔记】
  • 蓝色简洁引导页网站源码
  • 我们公司只有3个人,一个前端,一个后端
  • Java:基于springboot的高校实习管理系统的设计和开发
  • 浅谈棋牌游戏开发流程二:后端技术选型与基础环境搭建
  • 【SPIE独立出版,首届会议见刊后27天EI检索!高录用】第二届遥感、测绘与图像处理国际学术会议(RSMIP 2025)
  • 数据库高安全—角色权限:角色创建角色管理
  • 永磁同步电机预测模型控制(MPC)
  • 计算机网络 —— 网络编程(套接字深度理解)
  • 【漫话机器学习系列】034.决策树(Decision Tree)
  • Python自学 - 递归函数
  • 中型 UniApp 项目的挑战与突破
  • (九千七-星河襟)椭圆曲线加密(ECC, Elliptic Curve Cryptography)及其例题
  • 软考 高级 架构师 第十 章软件工程3