乐优商城项目---day13-搜索过滤

2.3.页面渲染

页面已经拿到了结果,接下来就要渲染样式了。

2.3.1.保存搜索结果

首先,在data中定义属性,保存搜索的结果:

这个页面渲染主要是涉及到Vue的相关的知识,相对来说如果前端的基础较差的话,理解起来还是比较费事的,因为没有JavaSSM三层结构那么的明显,所以这个前端的框架的部分的代码写起来相对来说比较费劲,不过也是有迹可循的,首先,要在Vue中定义到获取的模型的对象,之后才能对模型进行操作,操作完之后,在把处理的结果集合返回到页面,然后页面在进行渲染,这个流程,在执行的过程中,就代码的书写比较难受。

首先,在data中定义属性,保存搜索的结果: 这个事定义了一个goodsList的一个集合,这个集合里面就用来存放后端响应的所有的数据

其实这个操作其实非常的简单,就是分了两个步骤,第一个步骤定义一个goodsLsit,集合,把响应的数据存入到goodsList集合中,第二个步骤就是循环遍历goodsList,将数据渲染到前台的模板上

2.3.3.多sku展示

2.3.3.1.分析

接下来展示具体的商品信息,来看图:

因为一个Spu下有多个SKu,所以存在多SKU的问题,这个时候处理的方法就事将Sku转换为单个的对象,然后在将对象显示到页面上,之后处理起来就比较简单了

这里我们可以发现,一个商品位置,是多个sku的信息集合。当用户鼠标选择某个sku,对应的图片、价格、标题会随之改变!

我们先来实现sku的选择,才能去展示不同sku的数据。

可以看到,在列表中默认第一个是被选中的,那我们就需要做两件事情:

  • 在搜索到数据时,先默认把第一个sku作为被选中的,记录下来

  • 记录当前被选中的是哪一个sku,记录在哪里比较合适呢?显然是遍历到的goods对象自己内部,因为每一个goods都会有自己的sku信息。

这个时候只要在给响应过的goodsList中的单个的goods对象在附加一个select的属性就可以l了

这个鼠标的动态渲染,和鼠标划过图片要有变化的效果注意两个地方,因为Vue不能监听后来附加上的属性,应该事先转化对象,在添加属性,最后在把对象赋值给goodsList,这样就可以监听了

 

3.页面分页效果

刚才的查询中,我们默认了查询的页码和每页大小,因此所有的分页功能都无法使用,接下来我们一起看看分页功能条该如何制作。

这里要分两步,

  • 第一步:如何生成分页条

  • 第二步:点击分页按钮,我们做什么

这个分页在写的时候有一些坑,这个前端这个代码不好调试的问题就是,你单词拼错,或则是少一个分号,页面直接就不显示了,也不提示什么异常,排查错误很难排查,非常建议这块提前把代码备份好,或者调试一步,在走下一步,否则非常大的可能会出现,上一次调试还好好的,突然加了一个方法,直接页面就不显示了,可能就是少了一个分号,或者多了一个大括号,页面就渲染不出来了,比如这种错误;

开始进行前端分页的页面渲染:

因为后台已经提供过了totalPage:所以只用去过了,存到模型对象里面,然后在对这个模型对象里面的当前页做处理就可以了

 分页正常显示出来:

 

wahtch:{
  search:{
      deep:true,
      handler(){
          this.loadData();
      }
  }
},

翻页过后出现无限循环已经地址栏和底部栏的数字页码对不上

刷新之后出现问题

找到原因:watch单词拼写错误,这个前端出现异常真的很难排查出来错误在哪

将这个地方的监听函数修改之后,分页渲染正常,这个Vue客户端的错误真的很难找到,前端的页面不号排查

 顶部分页条信息显示正常:

接下来就是对分类和品牌的聚合,聚合之后进行对页面的渲染,因为用的是查询里面的聚合词条的方法,所以主要是对两个函数内容的编写:

根据BrandId进行聚合:

 /**
     * 解析品牌的聚合结果集合
     * @param aggregation
     * @return
     */
    private List<Brand> gerBrandAggResult(Aggregation aggregation) {
        LongTerms terms= (LongTerms) aggregation;
        List<Brand> brands=new ArrayList<>();
        terms.getBuckets().forEach(bucket -> {
            Brand brand = this.brandClient.queryNameById(bucket.getKeyAsNumber().longValue());
            brands.add(brand);
        });
        return brands;
    }

 根据分类Id进行聚合:

/**
     * 解析分类的聚合结果集
     * @param aggregation
     * @return
     */
    private List<Map<String, Object>> getCategoryAggResult(Aggregation aggregation) {
        LongTerms terms= (LongTerms) aggregation;
        List<Map<String,Object>> maps=new ArrayList<>();
        terms.getBuckets().forEach(bucket -> {
            Map<String,Object> map=new HashMap<>();
            long id = bucket.getKeyAsNumber().longValue();
            List<String> names = this.categoryClient.queryNameByids(Arrays.asList(id));
            map.put("id",id);
            map.put("name",names);
            maps.add(map);
        });
        return maps;
    }

可以看到在进行分类聚合的时候有出现了异常

这个远程调用的异常经成出现:问题还是出现在根据分类查询的时候参数的个数不匹配

 

进行修改,这个Feign客户端抛出的异常,正常情况下都可以进行修改的

完成测试:品牌和分类聚合成功

聚合成功之后开始直接在页面上渲染数据

前端的代码渲写起来真的比较麻烦:

 

 完成渲染成功:

 开始封装规格参数封装规格参数的思路也是比较简单的,只要封装成,List<Map<String,Object>>这种机构就可以了,K为规格参数名,Value为规格参数值,这个数据结构有点复杂,首先是规格参数名,是Map结构,规格参数值,是Map<List>的结构,最后整个响应的结果集合是个List<Map>的结构,所以比较绕,但是也可也写的通

    /**
     * 根据查询条件聚合规格参数
     * @param id
     * @param baseQuery
     * @return
     */
    private List<Map<String, Object>> getParamAggResult(Long id, QueryBuilder baseQuery) {
        //构建查询对象
        NativeSearchQueryBuilder queryBuilder=new NativeSearchQueryBuilder();
        //保留关键字查询
        queryBuilder.withQuery(baseQuery);
        List<Map<String, Object>>specs=new ArrayList<>();
        //查询要执行聚合的规格参数
        List<SpecParam> specParamList = this.specificationClient.querySpecParam(null, id, null, true);
        //将每个规格参数放入聚合从查询条件中
        specParamList.forEach(specParam -> {
            queryBuilder.addAggregation(AggregationBuilders.terms(specParam.getName()).field("specs."+specParam.getName()+".keyword"));
        });
        //排除字段
        queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{},null));
        //执行查询
        AggregatedPage<Goods> goodsPage = (AggregatedPage<Goods>) this.goodsRepository.search(queryBuilder.build());
        //解析聚合查询
        Map<String, Aggregation> aggregationMap = goodsPage.getAggregations().asMap();
        //遍历聚合查询出来的条件开始进行封装
        for (Map.Entry<String, Aggregation> entry : aggregationMap.entrySet()) {
            Map<String,Object> map=new HashMap<>();
            map.put("k",entry.getKey());
            StringTerms options = (StringTerms) entry.getValue();
            List<String> ops=new ArrayList<>();
            options.getBuckets().forEach(bucket -> {
                ops.add(bucket.getKeyAsString());
            });
            map.put("options",ops);
            specs.add(map);
        }


        return specs;
    }

完成测试

开始渲染出来静态页面:

 data.specs.forEach(spec=>{
                    spec.options=spec.options.map(o=>({name:o}))
                this.filters.push(spec);
                })

更多收起页面优化

 <div class="type-wrap" style="text-align: center">
                <v-btn small flat @click="show=true" v-show="!show">
                    更多
                    <v-icon>arrow_drop_down</v-icon>
                </v-btn>
                <v-btn small="" flat @click="show=false" v-show="show">
                    收起
                    <v-icon>arrow_drop_up</v-icon>
                </v-btn>
            </div

发送请求,将规格参数的列表的值发送请求封装过去

selectFilter(k,option){
                let obj={};
                Object.assign(obj,this.search);
                if (k=="品牌"|| k=="分类"){
                    obj.filter[k]=option.id;
                }else{
                    obj.filter[k]=option.name
                }
                this.search=obj;
            }

添加过滤查询:

   private BoolQueryBuilder buildBoolQueryBuid(SearchRequest searchRequest) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //给布尔查询添加基本的查询条件
        boolQueryBuilder.must(QueryBuilders.matchQuery("all",searchRequest.getKey()).operator(Operator.AND));
        //添加过滤条件
        Map<String, Object> filter = searchRequest.getFilter();
        for (Map.Entry<String, Object> stringObjectEntry : filter.entrySet()) {
            String key = stringObjectEntry.getKey();
            if (StringUtils.equals("品牌",key)){
            key="brandId";
            }else if (StringUtils.equals("分类",key)){
              key="cid3";
            }else{
                key="specs."+key+".keyword";
            }
            boolQueryBuilder.filter(QueryBuilders.termQuery(key,stringObjectEntry.getValue()));
        }
        return boolQueryBuilder;
    }

完成测试:

今日总结:这个搜索的结果和微服务算是结束了,搜索的API和语法过程都不太熟悉,所以写起来这些程序非常的吃力,出现BUG也好寻找,加上VUE也部熟练,所以写这些程序比较困难,不过总算是把这个搜索引擎这个微服务给写出来了,后面在碰到这个搜索引擎,起码有个印象,还得靠API文档。

发布了143 篇原创文章 · 获赞 16 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/zgz102928/article/details/104517089