二十八、商城 - 搜索解决方案-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("<em style='color:red'>");
     //4、设置高亮后缀
     options.setSimplePostfix("</em>");
     //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;
 }

注意:一定要判断高亮结果集合是否为空,因为搜索的是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<TbItem> tbItems = solrTemplate.queryForPage(query, TbItem.class);

    List<TbItem> itemList = tbItems.getContent();

    long total = tbItems.getTotalElements();

    map.put("rows",itemList);

    map.put("total",total);*/

    //1.查询列表

    map.putAll(searchList(searchMap));

    return map;
}

开启 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);
    }
}]);

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

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

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

检测:👇🏾👇🏾

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

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

在这里插入图片描述

二、搜索业务规则分析

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;
}

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<TbItem> tbItems = solrTemplate.queryForPage(query, TbItem.class);

    List<TbItem> 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;
}

在这里插入图片描述

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><!--  <a href="#">电视</a>-->
				</div>
				<div class="fl ext"></div>
			</div>

在这里插入图片描述

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

在这里插入图片描述

四、缓存品牌和规格数据

4.1 需求分析

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

  • (1)当用户进入运营商后台的商品分类页面时,将商品分类数据放入缓存(Hash)。以分类名称作为key ,以模板ID作为值
    当用户进入运营商后台的模板管理页面时,分别将品牌数据和规格数据放入缓存(Hash)。以模板ID作为key,以品牌列表和规格列表作为值。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Daniel521-Spark

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

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

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

打赏作者

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

抵扣说明:

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

余额充值