• 二十八、商城 - 搜索解决方案-Solr(16)【2】


    一、优乐选-高亮显示

    1.1 需求分析

    将用户输入的关键字在标题中以红色的字体显示出来,就是搜索中常用的高亮显示.

    在这里插入图片描述

    1.2 后端代码

    修改工程(youlexuan_search_service)服务层代码 ItemSearchServiceImpl.java

    创建私有方法,用于返回查询列表的结果(高亮)

    //高亮显示
     public Map searchList(Map searchMap){
    
         Map<String, Object> map = new HashMap<>();
         //1、创建一个支持高亮查询器对象
         SimpleHighlightQuery query = new SimpleHighlightQuery();
         //2、设定需要高亮处理字段
         HighlightOptions options = new HighlightOptions();
         options.addField("item_title");
         //3、设置高亮前缀
         options.setSimplePrefix("");
         //4、设置高亮后缀
         options.setSimplePostfix("");
         //5、关联高亮选项到高亮查询器对象
         query.setHighlightOptions(options);
         //6、设定查询条件 根据关键字查询
         //创建查询条件对象
         Criteria criteria = new Criteria("item_keywords").is(searchMap.get("keywords"));
         //关联查询条件到查询器对象
         query.addCriteria(criteria);
         //7、发出带高亮数据查询请求
         HighlightPage<TbItem> highlightPage = solrTemplate.queryForHighlightPage(query, TbItem.class);
         //8、获取查询结果记录集合
         List<TbItem> list = highlightPage.getContent();
         //9、循环集合对象
         for (TbItem tbItem : list) {
             //获取到针对对象TbItem高亮集合
             List<HighlightEntry.Highlight> highlights = highlightPage.getHighlights(tbItem);
             //获取第一个字段高亮对象
             if(highlights != null && highlights.size() > 0){
                 List<String> snipplets = highlights.get(0).getSnipplets();
    
                 System.out.println("高亮:"+snipplets.get(0));
                 //使用高亮结果替换商品标题
                 tbItem.setTitle(snipplets.get(0));
             }
    
         }
    
         map.put("rows",highlightPage.getContent());
    
         return map;
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    注意:一定要判断高亮结果集合是否为空,因为搜索的是item_keywords,高亮处理的是item_title所以不是所有查询到的结果都一定有高亮,需要对高亮结果集合判断是否为空。

    修改ItemSearchServiceImpl 的search方法,调用刚才编写的私有方法

    @Override
    public Map<String, Object> search(Map searchMap) {
    
        Map<String, Object> map = new HashMap<>();
    
        /*SimpleQuery query = new SimpleQuery();
    
        // is:基于分词后的结果 和 传入的参数匹配
        Criteria criteria = new Criteria("item_keywords").is(searchMap.get("keywords"));
    
        // 添加查询条件
        query.addCriteria(criteria);
    
        ScoredPage tbItems = solrTemplate.queryForPage(query, TbItem.class);
    
        List itemList = tbItems.getContent();
    
        long total = tbItems.getTotalElements();
    
        map.put("rows",itemList);
    
        map.put("total",total);*/
    
        //1.查询列表
    
        map.putAll(searchList(searchMap));
    
        return map;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    开启 search_service,search_web

    测试:http://localhost:9104/search.html

    在这里插入图片描述

    我们测试后发现高亮显示的html代码原样输出,这是angularJS为了防止html攻击采取的安全机制。我们如何在页面上显示html的结果呢?我们会用到$sce服务的trustAsHtml方法来实现转换。
    因为这个功能具有一定通用性,我们可以通过angularJS的过滤器来简化开发,这样只写一次,调用的时候就非常方便了,看下面:

    1.3 前端代码

    (1)修改 base.js

    /*$sce服务写成过滤器,因为search.html中引入得是base.js所以就写到这里了*/
    app.filter('trustHtml',['$sce',function($sce){
        return function(data){
            return $sce.trustAsHtml(data);
        }
    }]);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述
    (2)使用过滤器

    • ng-bind-html指令用于显示html内容
    • 竖线 |用于调用过滤器
    <div class="attr"  ng-bind-html="item.title | trustHtml">
    	<em>{{item.title}}em>
    div>
    
    • 1
    • 2
    • 3

    在这里插入图片描述
    刷新页面还是不显示高亮:

    检测:👇🏾👇🏾

    在这里插入图片描述
    解决:

    刷新页面——> 清空缓存,则成功显示:

    在这里插入图片描述

    二、搜索业务规则分析

    2.1 需求分析

    今天要完成的目标是在关键字搜索的基础上添加面板搜索功能
    面板上有商品分类、品牌、各种规格和价格区间等条件

    在这里插入图片描述

    业务规则:

    (1)当用户输入关键字搜索后,除了显示列表结果外,还应该显示通过这个关键字搜索到的记录都有哪些商品分类。
    (2)根据第一个商品分类查询对应的模板,根据模板查询出品牌列表
    (3)根据第一个商品分类查询对应的模板,根据模板查询出规格列表
    (4)当用户点击搜索面板的商品分类时,显示按照这个关键字查询结果的基础上,筛选此分类的结果。
    (5)当用户点击搜索面板的品牌时,显示在以上结果的基础上,筛选此品牌的结果
    (6)当用户点击搜索面板的规格时,显示在以上结果的基础上,筛选此规格的结果
    (7)当用户点击价格区间时,显示在以上结果的基础上,按价格进行筛选的结果
    (8)当用户点击搜索面板的相应条件时,隐藏已点击的条件。

    2.2 实现思路

    (1)搜索面板的商品分类需要使用Spring Data Solr的分组查询来实现
    (2)为了能够提高查询速度,我们需要把查询面板的品牌、规格数据提前放入redis
    (3)查询条件的构建、面板的隐藏需要使用angularJS来实现
    (4)后端的分类、品牌、规格、价格区间查询需要使用过滤查询来实现

    三、查询分类列表

    3.1 需求分析

    根据搜索关键字查询商品分类名称列表

    在这里插入图片描述

    3.2 后端代码

    修改SearchItemServiceImpl.java创建方法

    //商品分类
    private  List searchCategoryList(Map searchMap){
    
        List<String> list = new ArrayList<>();
    
        SimpleQuery query = new SimpleQuery();
        //按照关键字查询
        Criteria criteria= new Criteria("item_keywords").is(searchMap.get("keywords"));
    
        query.addCriteria(criteria);
        //设置分组选项
        GroupOptions groupOptions = new GroupOptions().addGroupByField("item_category");
    
        query.setGroupOptions(groupOptions);
    
        //得到分组页
        GroupPage<TbItem> groupPage = solrTemplate.queryForGroupPage(query, TbItem.class);
    
        //根据列得到分组结果集
        GroupResult<TbItem> groupResult = groupPage.getGroupResult("item_category");
    
        //得到分组结果入口页
        Page<GroupEntry<TbItem>> groupEntries = groupResult.getGroupEntries();
        //得到分组入口集合
        List<GroupEntry<TbItem>> content = groupEntries.getContent();
    
        for (GroupEntry<TbItem> itemGroupEntry : content) {
    
    
            list.add(itemGroupEntry.getGroupValue());//将分组结果的名称封装到返回值中
        }
    
        return list;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    search方法调用

    @Override
    public Map<String, Object> search(Map searchMap) {
    
        Map<String, Object> map = new HashMap<>();
    
        /*SimpleQuery query = new SimpleQuery();
    
        // is:基于分词后的结果 和 传入的参数匹配
        Criteria criteria = new Criteria("item_keywords").is(searchMap.get("keywords"));
    
        // 添加查询条件
        query.addCriteria(criteria);
    
        ScoredPage tbItems = solrTemplate.queryForPage(query, TbItem.class);
    
        List itemList = tbItems.getContent();
    
        long total = tbItems.getTotalElements();
    
        map.put("rows",itemList);
    
        map.put("total",total);*/
    
        //1.查询列表
    
        map.putAll(searchList(searchMap));
    
        //2.根据关键字查询商品分类
        List categoryList = searchCategoryList(searchMap);
    
        map.put("categoryList",categoryList);
        return map;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    在这里插入图片描述

    3.3 前端代码

    修改search.html

    <div class="clearfix selector" ng-if="resultMap.categoryList != null">
    			<div class="type-wrap">
    				<div class="fl key">商品分类div>
    				<div class="fl value" ng-repeat="category in resultMap.categoryList">
    					<a href="#">{{category}}a>
    				div>
    				<div class="fl ext">div>
    			div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    测试:http://localhost:9104/search.html

    在这里插入图片描述

    四、缓存品牌和规格数据

    4.1 需求分析

    将商品分类数据、品牌数据、和规格数据都放入Redis存储。

    • (1)当用户进入运营商后台的商品分类页面时,将商品分类数据放入缓存(Hash)。以分类名称作为key ,以模板ID作为值
      当用户进入运营商后台的模板管理页面时,分别将品牌数据和规格数据放入缓存(Hash)。以模板ID作为key,以品牌列表和规格列表作为值。
  • 相关阅读:
    在ubuntu中恢复误删除的文件
    SSL证书对于SEO优化的重要性
    MATLAB算法实战应用案例精讲-【集成算法】集成学习模型Bagging(附Python和R语言代码)
    搞定ESD(二):ESD干扰机理分析
    UE4学习笔记:如何在场景中播放视频
    MyBatis 学习(四)之 SQL 映射文件
    关于使用Mxnet GPU版本运行DeepAR报错解决方案
    71.【MySQL-二刷】
    linux 安装 jdk 环境
    提高Oracle数据库缓存命中率
  • 原文地址:https://blog.csdn.net/weixin_42171159/article/details/126524149