谷粒商城-商城业务-检索服务

目录

商城业务-检索服务-搭建页面环境

商城业务-检索服务-调整页面跳转

商城业务-检索服务-检索查询参数模型分析抽取

商城业务-检索服务-检索返回结果模型分析抽取

商城业务-检索服务-检索DSL测试-查询部分

商城业务-检索服务-检索DSL测试-聚合部分

商城业务-检索服务-SearchRequest构建-检索

商城业务-检索服务-SearchRequest构建-排序、分页、高亮&测试

商城业务-检索服务-SearchRequest构建-聚合

商城业务-检索服务-SearchRequest构建-分析&封装

商城业务-检索服务-验证结果封装正确性

商城业务-检索服务-页面数基本数据渲染

商城业务-检索服务-页面筛选条件渲染

商城业务-检索服务-页面分页数据渲染

商城业务-检索服务-页面排序功能

商城业务-检索服务-页面排序字段回显

商城业务-检索服务-页面价格区间搜索

商城业务-检索服务-面包屑导航

商城业务-检索服务-条件删除与URL编码问题

商城业务-检索服务-添加筛选联动


商城业务-检索服务-搭建页面环境

Nginx动静分离,将搜索页中的静态资源上传至/static/search文件夹下,将index.html搜索首页存放在gulimall-search服务的templates下

cd /mydata/nginx/html/static
mkdir search

 

 

使用thymeleaf模板引擎:

①导入thymeleaf的依赖

<!--导入thymeleaf依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

② 导入thymeleaf的命名空间

xmlns:th="http://www.thymeleaf.org"

③ 修改静态资源的请求路径,使用CTRL+R进行全部替换

所有动态请求search.gulimall.com的请求由Nginx转发给网关

①配置域名转发

②配置Nginx配置文件

cd /mydata/nginx/conf.d
vi gulimall.conf

重启nginx服务 

docker restart  nginx

③配置网关

        - id: gulimall_host_route
          uri: lb://gulimall-product  # lb:负载均衡
          predicates:
            - Host=gulimall.com   # **.xxx  子域名

        - id: gulimall_search_route
          uri: lb://gulimall-search  # lb:负载均衡
          predicates:
            - Host=search.gulimall.com   # **.xxx  子域名

商城业务-检索服务-调整页面跳转

配置热部署

①导入依赖

<!--导入热部署依赖-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-devtools</artifactId>
  <optional>true</optional>
</dependency>

② 开发期间默认关闭缓存

点击这几处要跳转到检索首页

鼠标右击,点击检查

修改请求路径

CTRL+F9重新编译 

出现错误:访问到80端口

出现问题的原因:nginx配置出错不能正确路由跳转 

解决方案:修改nginx配置文件

cd /mydata/nginx/conf/conf.d
vi gulimall.conf

重启nginx 

docker restart nginx

关闭Product服务的缓存,重启服务

  

首页,点击搜索按钮要来到搜索页

 点击手机1111111要来到搜索页

 

请求路径为http://search.gmall.com/list.html?catalog3Id=225,这是一个错误请求路径,缺少了gulimall而不是gumall

①将index.html修改为list.html

②编写控制类

③首页搜索栏修改为

④ 修改js并上传nginx,重启nginx

 结果:

商城业务-检索服务-检索查询参数模型分析抽取

①通过首页搜索栏进行检索,传递keyword

 ②通过分类进行检索。传递catalog3Id

 ③复杂查询

排序:①综合排序②销量③价格 ,例如:通过销量降序排序或者升序排序,sort=saleCount_desc/saleCount_asc

过滤:①库存,例如:有库存->hasStock=1,无库存 -> hasStock=0 ②价格区间 ,例如: 价格位于 400 -900 -> skuPrice=400_900,价格低于900 -> skuPrice= _900,价格高于900 -> skuPrice=900_  ③品牌: 可以按照多个品牌进行筛选

聚合:属性:多个属性以:分割,1号属性网络可以是4G也可以是5G -> attrs=1_4G:5G 

分页:页码

创建Vo,用于封装查询条件

商城业务-检索服务-检索返回结果模型分析抽取

以京东为例,搜索小米

默认:查询所有商品信息

1.小米所属的品牌 2.小米所属的分类 3.小米所属的属性

编写返回结果的Vo

商城业务-检索服务-检索DSL测试-查询部分

首先,这是一个复合查询即bool查询,将需要评分的检索条件写在must中,不需要评分的检索条件写在filter中。

①keyword的全文检索,例如:keyword=iphone

② 手机分类的检索,例如: catalogId=225 ,非文本字段检索用term

③ 品牌检索

④根据属性检索,属性未防止扁平化处理声明为nested,因此,需要使用nested查询

nested query文档地址:Nested query | Elasticsearch Guide [8.2] | Elastic

 

 ⑤是否有库存

 ⑥价格区间检索

⑦排序

⑧ 页码

⑨ 高亮,标题内容含有搜索内容则标题中含有的搜索内容标红

 

DSL语句:

GET /product/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "skuTitle": "iphone"
          }
        }
      ],
      "filter": [
        {
          "term": {
            "catalogId": {
              "value": "225"
            }
          }
        },
        {
          "terms": {
            "brandId": [
              "8",
              "9"
            ]
          }
        },
        {
          "nested": {
            "path": "attrs",
            "query": {
              "bool": {
                "must": [
                  {
                    "term": {
                      "attrs.attrId": {
                        "value": "1"
                      }
                    }
                  },
                  {
                    "terms": {
                      "attrs.attrValue": [
                        "5G",
                        "4G"
                      ]
                    }
                  }
                ]
              }
            }
          }
        },
        {
          "term": {
            "hasStock": {
              "value": "false"
            }
          }
        },
        {
          "range": {
            "skuPrice": {
              "gte": 4999,
              "lte": 5400
            }
          }
        }
      ]
    }
  },
  "sort": [
    {
      "skuPrice": {
        "order": "desc"
      }
    }
  ],
  "from": 0,
  "size": 10,
   "highlight": {
     "fields": {"skuTitle":{}},
     "pre_tags": "<b style='color:red'>",
     "post_tags": "</b>"
   }
}

商城业务-检索服务-检索DSL测试-聚合部分

①product映射有些数据类型不允许索引,因此,创建新的映射,允许索引

PUT /gulimall_product
{
  "mappings": {
    "properties": {
      "skuId":{
        "type": "long"
      },
      "spuId":{
        "type": "keyword"
      },
      "skuTitle":{
        "type": "text",
        "analyzer": "ik_smart"
      },
      "skuPrice":{
        "type": "keyword"
      },
      "skuImg":{
        "type": "keyword"
      },
      "saleCount":{
        "type": "long"
      },
      "hasStock":{
        "type": "boolean"
      },
      "hotScore":{
        "type": "long"
      },
      "brandId":{
        "type": "long"
      },
      "catelogId":{
        "type": "long"
      },
      "brandName":{
        "type": "keyword"
      },
      "brandImg":{
        "type": "keyword"
      },
      "catelogName":{
        "type": "keyword"
      },
      "attrs":{
        "type": "nested",
        "properties": {
          "attrId":{
            "type":"long"
          },
          "attrName":{
            "type": "keyword"
          },
          "attrValue":{
            "type":"keyword"
          }
        }
      }
    }
  }
}

 ②数据迁移

③修改索引常量

④品牌聚合

⑤分类聚合

⑥属性聚合,应使用嵌入式聚合

nested aggregations文档地址:Nested Aggregations | Elasticsearch: The Definitive Guide [2.x] | Elastic

⑦完整DSL

GET /gulimall_product/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "skuTitle": "iphone"
          }
        }
      ],
      "filter": [
        {
          "term": {
            "catalogId": {
              "value": "225"
            }
          }
        },
        {
          "terms": {
            "brandId": [
              "8",
              "9"
            ]
          }
        },
        {
          "nested": {
            "path": "attrs",
            "query": {
              "bool": {
                "must": [
                  {
                    "term": {
                      "attrs.attrId": {
                        "value": "1"
                      }
                    }
                  },
                  {
                    "terms": {
                      "attrs.attrValue": [
                        "5G",
                        "4G"
                      ]
                    }
                  }
                ]
              }
            }
          }
        },
        {
          "term": {
            "hasStock": {
              "value": "false"
            }
          }
        },
        {
          "range": {
            "skuPrice": {
              "gte": 4999,
              "lte": 5400
            }
          }
        }
      ]
    }
  },
  "sort": [
    {
      "skuPrice": {
        "order": "desc"
      }
    }
  ],
  "from": 0,
  "size": 10,
   "highlight": {
     "fields": {"skuTitle":{}},
     "pre_tags": "<b style='color:red'>",
     "post_tags": "</b>"
   },
   "aggs": {
    "brand_agg": {
      "terms": {
        "field": "brandId",
        "size": 10
      },
      "aggs": {
        "brand_name_agg": {
          "terms": {
            "field": "brandName",
            "size": 10
          }
        },
        "brand_img-agg": {
          "terms": {
            "field": "brandImg",
            "size": 10
          }
        }
      }
    },
    "catalog_agg":{
      "terms": {
        "field": "catalogId",
        "size": 10
      },
      "aggs": {
        "catalog_name_agg": {
          "terms": {
            "field": "catelogName",
            "size": 10
          }
        }
      }
    },
    "attr_agg":{
      "nested": {
        "path": "attrs"
      },
      "aggs": {
        "attr_id_agg": {
          "terms": {
            "field": "attrs.attrId",
            "size": 10
          },
          "aggs": {
            "attr_name_agg": {
              "terms": {
                "field": "attrs.attrName",
                "size": 10
              }
            },
            "attr_value_agg":{
              "terms": {
                "field": "attrs.attrValue",
                "size": 10
              }
            }
          }
        }
      }
    }
  }
}

⑧将gulimall_product映射和DSL进行保存

商城业务-检索服务-SearchRequest构建-检索

编写接口

导入ES客户端对象

整体逻辑:1.封装DSL 2.查询 3.封装响应结果

开始封装DSL 

1.构建bool查询

2. 构建must查询

3. 构建filter中三级分类查询

4.构建filter中的品牌查询

5.构建filter中的库存查询

6.构建filter中的价格区间查询

7. 构建filter中的属性查询

商城业务-检索服务-SearchRequest构建-排序、分页、高亮&测试

1.构建排序

2. 构建分页

默认页码为1,页码大小为2方便测试

3.构建高亮

进行简单的测试,将打印的DSL复制到Kibana中看是否正确

商城业务-检索服务-SearchRequest构建-聚合

1.品牌聚合

2.分类聚合

3.属性聚合

商城业务-检索服务-SearchRequest构建-分析&封装

打上断点,根据返回的response封装响应结果

 1对应于2

 

1. 封装所有记录

2. 封装品牌,聚合返回的类型可以从断点返回结果查看

3.封装分类

4.封装属性

5.封装页码

6.封装总记录数

7.封装总页数

商城业务-检索服务-验证结果封装正确性

高亮设置

商城业务-检索服务-页面数基本数据渲染

由于有库存的商品非常少,因此,不设置库存的默认值,前端传进来的参数不为空时再拼装上查询条件

将分页大小设置为16 

动态获取页面显示数据 

①商品显示

 注意细节:th:text 会进行转义 ,th:utext不会进行转义

如果使用th:text,带keyword高亮之后,则会出现下面的结果:

 ②品牌显示

③分类显示 

④ 属性显示

商城业务-检索服务-页面筛选条件渲染

1.按品牌条件筛选,&quot="

2.按分类条件筛选

3.按属性条件筛选

4. url拼接函数编写

商城业务-检索服务-页面分页数据渲染

1.搜索栏功能完成

 为input创建id,方便后续拿到input中的输入;编写跳转方法

 

 搜索框回显搜索内容,th:value 为属性设置值 ;param是指请求参数,param.keyword是指

 请求参数中的keyword值

2.分页功能的完善

① 当前页码>第一页才能显示上一页,当前页码<总页码才能显示下一页

② 自定义属性用于保存当前页码,作用:用于替换请求参数中的pageNum值

③遍历显示页码

 

④ 当前页码显示特定的样式

⑤ 请求参数的替换

将a标签中href全部删除,添加a标签的class,为其绑定事件,并编写回调函数

$(this)指当前被点击的元素,return false作用:禁用默认行为,a标签可能会跳转

替换方法 

function replaceParamVal(url,paramName,replaceVal){
        var oUrl = url.toString();
        var re = eval('/('+paramName+'=)([^&]*)/gi');
        var nUrl = oUrl.replace(re,paramName+'='+replaceVal);
        return nUrl;
    }

商城业务-检索服务-页面排序功能

为a标签定义class 

为a标签绑定点击事件 

为选中的元素设置样式

 为选中的元素设置样式之前需要将所有元素的样式恢复成最初样式

使用toggleClass()为class加上desc,默认为降序排序 

添加升降符号 

$(this).text()获取当前点击元素的文本内容

添加升降符号之前需要清空元素的升降符号

将被选中元素的样式改变抽取成一个方法 

function changeStyle(ele){
        $(".sort_a").css({"color":"#333","border-color":"#CCC","background":"#FFF"})
        $(ele).css({"color":"#FFF","border-color":"#e4393c","background":"#e4393c"})
        $(ele).toggleClass("desc");
        $(".sort_a").each(function (){
            var text = $(this).text().replace("↓","").replace("↑","");
            $(this).text(text);
        });
        if ($(ele).hasClass("desc")){
            var text = $(ele).text().replace("↓","").replace("↑","");
            text = text+"↓";
            $(ele).text(text);
        }else {
            var text = $(ele).text().replace("↓","").replace("↑","");
            text = text+"↑";
            $(ele).text(text);
        }
    }

自定义属性赋值为某种排序

改写替换方法

    function replaceOrAddParamVal(url,paramName,replaceVal){
        var oUrl = url.toString();
        if (oUrl.indexOf(paramName)!=-1){
            var re = eval('/('+paramName+'=)([^&]*)/gi');
            var nUrl = oUrl.replace(re,paramName+'='+replaceVal);
            return nUrl;
        }else {
            if (oUrl.indexOf("?")!=-1){
                var nUrl = oUrl+"&"+paramName+"="+replaceVal;
                return nUrl;
            }else {
                var nUrl = oUrl+"?"+paramName+"="+replaceVal;
                return nUrl;
            }
        }
    }

跳转指定路径

出现问题: 通过toggleClass()为class添加desc,刷新或者跳转之后会丢失

商城业务-检索服务-页面排序字段回显

页面跳转之后样式回显,th:with 用于声明变量,#strings即调用字符串工具类

根据URL动态添加class 

动态的添加升降符号 

商城业务-检索服务-页面价格区间搜索

编写价格区间搜索栏

为button按钮绑定单击事件 

价格回显 

①获取skuPirce的值

②价格区间回显 

#strings.substringAfter(name,prefix):获取prifix之后的字符串

#strings.substringBefore(name,suffix):获取suffix之前的字符串

拼接是否有货查询条件

为单选框绑定改变事件 

通过调用prop('check')获取是否被选中,选中为true否则false 

回显选中状态 

商城业务-检索服务-面包屑导航

 ①编写面包屑导航栏Vo

② 封装面包屑导航栏数据

属性名的获取要通过远程服务调用product服务进行查询 

①导入cloud的版本

<spring-cloud.version>Hoxton.SR9</spring-cloud.version>

② 导入cloud依赖管理

  <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

③ 导入openfeign的依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

④ 开启远程服务调用功能

⑤编写接口,配置调用的服务名 

⑥编写调用服务的接口,注意:全路径

⑦编写自己传key和返回值类型获取自己想要的数据类型方法,之前的只能获取data的数据

⑧编写返回类型的Vo,Vo和AttrRespVo属性一致

 

⑨封装属性名 

商城业务-检索服务-条件删除与URL编码问题

①封装原生的查询条件

HttpServletRequest的getQueryString()方法可以获取url的请求参数

②封装链接 

出现问题:路径替换失败

出现问题的原因:浏览器会将中文进行一个编码,而查询出来的属性值是中文

解决方案:将中文进行编码

注意:有些符号,浏览器的编码与java编码不一致

例如:'(':浏览器不进行编码,java会编码成%28;')':浏览器不进行编码,java会编码成%29;空格浏览器会编码成%20,java会编码成'+'

  // 8.封装面包屑导航栏的数据
        if (param.getAttrs()!=null && param.getAttrs().size()>0){
            List<SearchResVo.NavVo> navVoList = param.getAttrs().stream().map(item -> {
                SearchResVo.NavVo navVo = new SearchResVo.NavVo();
                String[] s = item.split("_");
                // 封装属性值
                navVo.setAttrValue(s[1]);

                //封装属性名
                R r = productFeignService.info(Long.parseLong(s[0]));
                if (r.getCode() == 0){
                    AttrResponseVo responseVo = r.getData("attr", new TypeReference<AttrResponseVo>() {});
                    navVo.setAttrName(responseVo.getAttrName());
                }else {
                    // 出现异常则封装id
                    navVo.setAttrName(s[0]);
                }

                //封装链接即去掉当前属性的查询的url封装
                String encode=null;
                try {
                    encode = URLEncoder.encode(item,"UTF-8");
                    encode=encode.replace("%28","(").replace("%29",")").replace("+","%20");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                String replace = param.get_queryString().replace("&attrs=" + encode, "");
                navVo.setLink("http://search.gulimall.com/list.html?"+replace);
                return navVo;
            }).collect(Collectors.toList());
            searchResVo.setNavs(navVoList);
        }

导航栏回显编写

①右击检测,找到元素

 

改写 replaceOrAddParamVal默认是对属性进行一个替换,forceAdd是否强制添加的标识

商城业务-检索服务-添加筛选联动

完善品牌面包屑导航栏功能,分类面包屑导航栏也类似,不同之处是不用剔除,设置url

①为面包屑vo设置一个默认值

② 远程调用product服务查询品牌名称

 

远程服务调用,查询很费时,可以将查询的结果保存进缓存中 ,例如:

value:分区名,key:用于标识第几号属性

③将封装替换url的方法抽取出来 

④编写面包屑导航栏功能

品牌面包屑导航栏,品牌筛选剔除

⑤创建一个list用于封装已经筛选的属性id

 

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用中提供的信息,谷粒商城是一个B2C模式的电商平台,主要销售自营商品给客户。B2C模式指的是商对客的模式,即商家直接向消费者销售商品和服务谷粒商城使用微服务架构,这是一种将应用程序拆分成独立且可独立开发、部署和扩展的小型服务的架构。引用还提到谷粒商城的技术涵盖微服务架构、分布式、全栈、集群、部署和自动化运维等方面。 因此,从前慢-谷粒商城篇章6主要讨论的可能是谷粒商城的技术方面,包括微服务架构、分布式、全栈、集群、部署和自动化运维等内容。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [从前慢-谷粒商城篇章1](https://blog.csdn.net/m0_67391121/article/details/125383572)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [2020年谷粒商城md笔记](https://download.csdn.net/download/ZHUXIUQINGIT/12543161)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值