zoukankan      html  css  js  c++  java
  • 分布式高级篇(四)

    分布式高级篇(四) - 商城业务 - 检索服务

    检索服务

    检索服务基础环境搭建

    • 最终效果

      image-20210115101004052

    • 效果演示

      • 1、全文检索:skuTitle -> keyword
      • 2、排序:saleCount(销量)、hotScore(热度评分)、skuPrice(价格)
      • 3、过滤:hasStock(是否有货)、skuPrice(价格区间)、brandId(品牌id 可以多选)、catalogId
      • 4、聚合:attrs(属性)
      • 5、面包屑导航
      • 6、条件删除&条件筛选联动

    搭建页面环境

    • 第一步:search微服务导入依赖

       <!--模板引擎 thymeleaf-->
       <dependency>
       	<groupId>org.springframework.boot</groupId>
       	<artifactId>spring-boot-starter-thymeleaf</artifactId>
       </dependency>
       <!--dev-tools-->
       <dependency>
       	<groupId>org.springframework.boot</groupId>
       	<artifactId>spring-boot-devtools</artifactId>
       	<optional>true</optional>
       </dependency>
      

      将检索页面 index.html,拷贝进项目,放入templates目录下

      image-20210115101713282

    • 第二步:修改本地Hosts文件

      目的使 search.mall.com 生效,访问search.mall.com相当于直接访问 nginx

      C:WindowsSystem32driversetc
      

      image-20210115095652050

      修改成功后,保存hosts,页面访问search.mall.com查看效果(确报nginx容器启动)

      image-20210115095725521

    • 第三步:将页面所需的静态资源拷贝进nginx中的 html/static/search 目录下(利用xshell和xftp)

      image-20210115102244480

      修改nginx 转发配置 在 nginx/conf/conf.d 目录下的 mall.conf,只要是以mall.com结尾的请求地址,匹配上/static/,都会请求nginx下的静态资源。修改完成 保存退出并重启nginx容器(docker restart nginx)

      image-20210115111312980

    • 第四步:修改index.html 中的所有静态资源访问路径 href 与 src标签的 统一加上/static/search/

      image-20210115102826321

      网关服务 添加新的路由规则 Host为search.mall.com的 统一转交给search服务处理,并重启网关服务

      image-20210115102919340

    测试

    • 确保search搜索服务 网关服务都成功注册进nacos服务注册中心

      image-20210115103405982

    • nginx容器配置修改并重启

    • 浏览器访问 search.mall.com,出现如下效果则搭建完成

      image-20210115104603707

    检索业务分析

    检索参数模型分析抽取

    • 商品检索的三个入口:

      • 1、首页--选择商品分类进入商品检索(分类catalogId)

        image-20210115132430506

      • 2、输入检索关键字展示检索页 (搜索关键字keyword)

        image-20210115132458037

      • 3、选择筛选条件进入

        image-20210115132637280

    • 检索条件分析

      • 1、全文检索:skuTitle -> keyword

      • 2、排序:saleCount(销量)、hotScore(热度评分)、skuPrice(价格)

      • 3、过滤:hasStock(是否有货)、skuPrice(价格区间)、brandId(品牌id 可以多选)、catalogId

      • 4、聚合:attrs(属性)

        完整请求参数: 
        catalog3Id=225&keyword=小米&hasStock=0/1&skuPrice=1_500&brandId=1&attrs=1_android:iOS&attrs=2_5.寸:6.5寸
        
        排序条件:sort=saleCount_asc/desc、sort=skuPrice_asc/desc、sort=hostScore_asc/desc
        hasStock(是否有货): hasStock=0/1
        skuPrice价格区间: skuPrice=1_500/_500/500_(1到500、500以内的、大于500的)
        brandId(品牌id 可以多选):brandId=1&brandId=2
        attrs(属性): attrs=1_android:iOS&attrs=2_5.寸:6.5寸
        

    检索结果模型分析抽取

    • 根据页面内容,抽取返回数据

      SearchResult
      
      查询到的所有商品信息
      当前页码
      总记录数
      总页码
      当前查询到的结果,所涉及到的所有品牌
      当前查询到的结果,所涉及到的所有分类
      当前查询的结果,所涉及到的所有属性
      

    检索语句构建(DSL)

    • 启动ES和kibana容器

    查询部分语句

    • 在kibana中先编写DSL语句,理清思路

      GET product/_search
      {
        "query": {
          "bool": {
            "must": [
              {
                "match": {
                  "skuTitle": "小米"
                }
              }
            ],
            "filter": [
              {
                "term": {
                  "catalogId": "225"
                }
              },
              {
                "terms": {
                  "brandId": [
                    "3",
                    "10"
                  ]
                }
              },
              {
                "nested": {
                  "path": "attrs",
                  "query": {
                    "bool": {
                      "must": [
                        {
                          "term": {
                            "attrs.attrId": {
                              "value": "13"
                            }
                          }
                        },
                        {
                          "terms": {
                            "attrs.attrValue": [
                              "android"
                            ]
                          }
                        }
                      ]
                    }
                  }
                }
              },
              {
                "term": {
                  "hasStock": {
                    "value": "true"
                  }
                }
              },
              {
                "range": {
                  "skuPrice": {
                    "gte": 100,
                    "lte": 4000
                  }
                }
              }
            ]
          }
        },
        "sort": [
          {
            "skuPrice": {
              "order": "desc"
            }
          }
        ],
        "from": 0,
        "size": 1,
        "highlight": {
          "fields": {"skuTitle": {}}, 
          "pre_tags": "<b style='color:red'>",
          "post_tags": "</b>"
        }
      }
      

      image-20210115162233410

      如果是嵌入式的属性 nested ,查询、聚合、分析都应该用嵌入式的

    DSL聚合分析

    ES数据迁移
    • 由于之前的ES中的 product索引 映射关系设置有些问题,我们可以新建一个新的mall_product索引,修改映射关系,并且把原有数据迁移进mall_product

      #数据迁移
      PUT mall_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"
            },
            "catalogId": {
              "type": "long"
            },
            "brandName": {
              "type": "keyword"
            },
            "brandImg": {
              "type": "keyword"
            },
            "catalogName": {
              "type": "keyword"
            },
            "attrs": {
              "type": "nested",
              "properties": {
                "attrId": {
                  "type": "long"
                },
                "attrName": {
                  "type": "keyword"
                },
                "attrValue": {
                  "type": "keyword"
                }
              }
            }
          }
        }
      }
      
      #转移product数据到mall_product
      #固定写法
      POST _reindex
      {
        "source": {
          "index": "product"
        },
        "dest": {
          "index": "mall_product"
        }
      }
      
      #查看数据迁移情况
      GET mall_product/_search
      {
        "query": {
          "match_all": {}
        }
      }
      
    聚合分析
    • 最终结果

      #检索 查询&聚合
      
      GET mall_product/_search
      {
        "query": {
          "bool": {
            "must": [
              {
                "match": {
                  "skuTitle": "小米"
                }
              }
            ],
            "filter": [
              {
                "term": {
                  "catalogId": "225"
                }
              },
              {
                "terms": {
                  "brandId": [
                    "3",
                    "10"
                  ]
                }
              },
              {
                "nested": {
                  "path": "attrs",
                  "query": {
                    "bool": {
                      "must": [
                        {
                          "term": {
                            "attrs.attrId": {
                              "value": "13"
                            }
                          }
                        },
                        {
                          "terms": {
                            "attrs.attrValue": [
                              "android"
                            ]
                          }
                        }
                      ]
                    }
                  }
                }
              },
              {
                "term": {
                  "hasStock": {
                    "value": "true"
                  }
                }
              },
              {
                "range": {
                  "skuPrice": {
                    "gte": 100,
                    "lte": 4000
                  }
                }
              }
            ]
          }
        },
        "sort": [
          {
            "skuPrice": {
              "order": "desc"
            }
          }
        ],
        "from": 0,
        "size": 1,
        "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_aggs": {
                "terms": {
                  "field": "catalogName",
                  "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
                    }
                  }
                }
              }
            }
          }
        }
      }
      
    • 分析过程

      当前查询到的结果 所有涉及到的所有品牌
      当前查询到的结果 所有涉及到的所有属性
      当前查询到的结果 所有涉及到的所有分类
      
      • 所有品牌(分类同理)

        GET mall_product/_search
        {
          "query": {
            "match_all": {}
          },
          "aggs": {
            "brand_agg": {
              "terms": {
                "field": "brandId",
                "size": 10
              }
            }
          }
        }
        

      image-20210116111242248

      • 想要顺便获取品牌的名称和品牌logo

        GET mall_product/_search
        {
          "query": {
            "match_all": {}
          },
          "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
                  }
                }
              }
            }
          }
        }
        

        image-20210116111527354

      • 当前查询结果下的所有属性(*)

        • 属性是nested的嵌套,所以聚合分析也应该是聚合的

          GET mall_product/_search
          {
            "query": {
              "match_all": {}
            },
            "aggs": {
              "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
                        }
                      }
                    }
                  }
                }
              }
            }
          }
          

        image-20210116112102484

    代码实现

    SearchRequest构建

    • java实现动态构建出查询需要DSL语句

      • 检索

        --bool query
          --must
            --term
          --filter
          	--term
          	--terms
          	--term
          	--range
          	--nested
          	  --bool
          	  	--must
          	  	  --term
          	  	  --term
        
      • 分页、排序、高亮

        image-20210116143403016

      • 聚合

        --brand_agg
          --brand_name_agg
          --brand_img_agg
        --catalog_agg
          --catalog_name_agg
        --nestedAttr_agg
          --attr_id_agg
          	--attr_name_agg
          	--attr_value_agg
        

        image-20210116145642688

    • 测试检索语句构建是否正确

      • 第一种:

        • postman 简单请求(keyword、catalog3Id)

        image-20210116131532127

        • 打印 searchSourceBuilder,并使用在线json格式化工具 格式化

          image-20210116131431640

        • 如果语句构建正确,可以直接拷贝到kibana中查询

          image-20210116131951561

      • 第二种:

        • 复杂筛选(属性attrs、价格区间)

          image-20210116142848804

        • image-20210116143111552

    • 测试聚合语句

      • postman模拟请求

        image-20210116145757702

      • 打印出的语句,拷贝到kibana

        image-20210116150207069

    SearchResponse分析&封装

    • 将ES返回结果进行封装

      1、返回的所有查询到的商品
      2、当前所有商品所涉及到的所有属性
      3、当前所有商品所涉及到的所有品牌信息
      4、当前所有商品所涉及到的所有分类信息
      5、分页信息
      

    页面渲染

    页面基本数据渲染

    • 检索数据展示

      image-20210117111422571

    • 刷选条件选择,请求路径拼接

      #&quot;brandId&quot; 代表"brandId" 前后双引号
      th:href="${'javascript:searchProducts(&quot;brandId&quot;,'+brand.brandId+')'}
      

      image-20210117111642760

    • 关键字检索

      image-20210117111724824

      检索条件回显

      image-20210117132928149

    • 分页数据渲染

      image-20210117133105478

    • 排序效果

      • 排序

      image-20210117142103168

      image-20210117142038846

      • 排序字段回显(页面跳转刷选之后)

        image-20210117154722635

    • 面包屑导航

      image-20210118152824857

      image-20210118152911565

    • 条件筛选联动

      image-20210118152958350

  • 相关阅读:
    Linked List Cycle leetcode java (链表检测环)
    Remove Duplicates from Sorted List II leetcode java
    Remove Duplicates from Sorted List leetcode java
    Merge Two Sorted Lists leetcode java
    Swap Nodes in Pairs leetcode java
    Median of Two Sorted Array leetcode java
    阿里云最便宜的四种域名注册
    nohup和&后台运行,进程查看及终止
    ipv6转ipv4 NAT64与DNS64基本原理概述
    ros使用pppoe拨号获取ipv6,并且下发IPV6的dns到客户机win7
  • 原文地址:https://www.cnblogs.com/w3angb/p/14293034.html
Copyright © 2011-2022 走看看