用户搜索es某些商品,该商品的属性和属性值很多相同的,使用数据结构的set集把它们全部去重,再去查询数据库,最后显示没重复的属性值!

本文介绍了在用户搜索商品时如何利用Java的Set数据结构去除ES查询结果中的重复属性值,避免使用低效的聚合函数。通过在Controller层和Service层的处理,将属性值ID转换为Set进行去重,并通过MyBatis进行数据库查询,减少了数据库连接次数,提高了性能。

一、显示这些平台属性值列表,是根据用户搜索的内容提取出来(剔除不符合的其他属性值),不全部显示平台属性值。

比如符合16G属性值的产品,用户点击16G,就把16G的产品中没有的属性值剔除
在这里插入图片描述
(1)可以使用es的aggregation聚合函数抽取平台属性
这个效率比较低,因为它不同于mysql,它这个聚合结果的过程损耗太多时间了。
es查询的效率虽然很高,但查询到的数据,使用聚合函数,还要统计每个商品拥有多少相同的属性值id,等待统计结果,再把它返回给你,性能较低!
在这里插入图片描述

// es的聚合函数aggs
TermsBuilder groupby_attr = AggregationBuilders.terms("groupby_attr").field("skuAttrValueList.valueId");
searchSourceBuilder.aggregation(groupby_attr);

这两行代码就可以统计每个商品拥有多少相同的属性值id,之后再创建一个es的属性值数据库,es根据统计的id去查询属性值名称并返回给java后端,再传到前端即可。

(2)使用java代码抽取平台属性
在这里插入图片描述

因为从es查询出来的结果列表数据,全部包含了属性值,我们可以直接使用!!!

A 计划(不推荐):
先到mysql查询skuId符合的相关平台属性值id,并且加distinct去重!(连数据库1次)
然后根据平台属性值id再去查询平台属性和属性值表,返回结果即可!(连数据库2次)
在这里插入图片描述

B计划,只需要连数据库1次,如果放到redis上,一次都不用连(推荐):
使用算法,使用for循环,使一个一个重复的id去掉,这样太笨了。

二、回归数据结构,使用set去重!!!

基础知识:
Java中的集合有三大类:set(集)、list(列表)、map(映射)
List(列表):元素有序可重复
Set(集):元素无序不可重复

Map(映射):标准的Java类库中包含了几种不同的Map:HashMap, TreeMap, LinkedHashMap。其中在制作sku商品详细页面的时候,就制作过哈希表map,用来提高查询效率!

故此,这里也可以应该java集合,使用set(集)自动去重(厉害吧):

(1)在controller层代码:

//使用set(集)去重,new一个HashSet列表
HashSet<String> hashSet = new HashSet<>();

for (PmsSearchSkuInfo pmsSearchSkuInfo : pmsSearchSkuInfos) {
    List<PmsSkuAttrValue> skuAttrValueList = pmsSearchSkuInfo.getSkuAttrValueList();
    for (PmsSkuAttrValue pmsSkuAttrValue : skuAttrValueList) {
        //遍历所查询到的商品的属性值id
        String valueId = pmsSkuAttrValue.getValueId();
        //把每一个属性值id都add进set(集)里,自动去重,重复的全部去掉,这一行代码解决所有问题啊,牛皮!!!
        hashSet.add(valueId);
    }
}

这里去重简单,拿到的不重复的属性值id后,
根据属性值id到数据库执行联合查询,查询平台属性和属性值两张表,把结果返回给前端即可。

//既然拿到了去重的属性值id,现在去操作数据 查询 平台属性和属性值
List<PmsBaseAttrInfo> pmsBaseAttrInfos = attrService.getBaseInfoAndValueList(hashSet);

modelMap.put("attrList",pmsBaseAttrInfos);

当然这里的不应该再连接数据库的,可以把属性和属性值放到redis中,去redis查询,减轻mysql的负担!

(2)去service层实现,首先要转换HashSet列表,多使用阿里和阿帕奇的转换工具。
这里使用阿帕奇的stringUtils的join进行转换,把它转为每个数字都用逗号隔开的字符串,再把这个字符串丢给mybatis进行联合查询即可!

//用户:查询平台属性和属性值返回给用户,供用户筛选属性值,找到合适的商品
@Override
public List<PmsBaseAttrInfo> getBaseInfoAndValueList(HashSet<String> hashSet) {

    
    String joins = StringUtils.join(hashSet, ",");
    List<PmsBaseAttrInfo> pmsBaseAttrInfos = pmsBaseAttrInfoMapper.selectBaseInfoAndValueList(joins);
    return pmsBaseAttrInfos;
}
SELECT
	*
FROM
	pms_base_attr_info a,
	pms_base_attr_value b
WHERE
	a.id = b.attr_id
AND b.id IN (39, 50, 60, 75, 93)

In后边的参数就是service传递给mybatis的字符串,用逗号隔开了!
在这里插入图片描述

(3)使用mybatis进行联表查询,跟之前的查询销售属性和属性值(涉及三张表)一样,需要对mybatis进行映射关系封装

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.gmall.manage.service.mapper.PmsBaseAttrInfoMapper">

    <select id="selectBaseInfoAndValueList" resultMap="selectBaseInfoAndValueListMap">
    SELECT
        a.id as a_id, b.id as b_id, a.*, b.*
    FROM
        pms_base_attr_info a,
        pms_base_attr_value b
    WHERE
        a.id = b.attr_id
    AND b.id IN (${joins})
    </select>

    <resultMap id="selectBaseInfoAndValueListMap" type="com.atguigu.gmall.bean.PmsBaseAttrInfo" autoMapping="true">

        <result column="a_id" property="id"></result>

        <collection property="attrValueList" ofType="com.atguigu.gmall.bean.PmsBaseAttrValue" autoMapping="true">

            <result column="b_id" property="id"></result>
        </collection>
    </resultMap>

</mapper>

(4)修改一下前端页面,因为美工在做京东的下拉属性值列表功能,未做成,把我的本来的东西隐藏了,所以这里修改一下,改成show即可。不然只能看到4条属性
在这里插入图片描述

(5)修改后,Ctrl+shift+f9提交一下,再刷新页面,正常显示了!
在这里插入图片描述

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值