添加模板页面

  1. <!-- 模板引擎 -->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-thymeleaf</artifactId>
  5. </dependency>

将资料中的前端页面放到 search 服务模块下的 resource/templates 下;

配置请求跳转

配置 Nginx 转发

配置 Windows hosts 文件:

  1. 192.168.163.131 search.gulimall.com

检索服务 - 图1
找到 Nginx 的配置文件,编辑 gulimall.conf,将所有 *.gulimall.com 的请求都经由 Nginx 转发给网关;

  1. server {
  2. listen 80;
  3. server_name gulimall.com *.gulimall.com;
  4. ...
  5. }

然后重启 Nginx
docker restart nginx

配置网关服务转发到 search 服务

- id: mall_search_route
  uri: lb://mall-search
  predicates:
  - Host=search.gulimall.com

配置页面跳转

配置 /list.html 请求转发到 list 模板

/**
 * 自动将页面提交过来的所有请求参数封装成我们指定的对象
 *
 * @param param
 * @return
 */
@GetMapping(value = "/list.html")
public String listPage(SearchParam param, Model model, HttpServletRequest request) {
    return "list";
}

检索功能

详细检索逻辑实现的代码请参考:Github

ES mall-product 映射 mapping修改

这里由于之前设置的映射 设置一些字段的 doc_value 为 false,导致后面聚合查询时报错!
修改完映射 mapping 要同步修改检索服务中的常量类中的 es 索引常量,二者要求对应。

# 查看原来的映射规则
GET gulimall_product/_mapping
# 修改为新的映射 并创建新的索引,下面进行数据迁移
PUT /mall_product
{
  "mappings": {
    "properties": {
      "skuId": {
        "type": "long"
      },
      "spuId": {
        "type": "long"
      },
      "skuTitle": {
        "type": "text",
        "analyzer": "ik_smart"
      },
      "skuPrice": {
        "type": "keyword"
      },
      "skuImg": {
        "type": "keyword"
      },
      "saleCount": {
        "type": "long"
      },
      "hosStock": {
        "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"
          }
        }
      }
    }
  }
}
# 数据迁移
POST _reindex
{
  "source": {
    "index": "gulimall_product"
  },
  "dest": {
    "index": "mall_product"
  }
}

ES 检索 DSL语句分析

GET mall_product/_search
{
  "query": {
    "bool": {
      "must": [ {"match": {  "skuTitle": "华为" }} ], # 检索出华为
      "filter": [ # 过滤
        { "term": { "catalogId": "225" } },
        { "terms": {"brandId": [ "2"] } }, 
        { "term": { "hasStock": "false"} },
        {
          "range": {
            "skuPrice": { # 价格1K~7K
              "gte": 1000,
              "lte": 7000
            }
          }
        },
        {
          "nested": {
            "path": "attrs", # 聚合名字
            "query": {
              "bool": {
                "must": [
                  {
                    "term": { "attrs.attrId": { "value": "6"} }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  },
  "sort": [ {"skuPrice": {"order": "desc" } } ],
  "from": 0,
  "size": 5,
  "highlight": {  
    "fields": {"skuTitle": {}}, # 高亮的字段
    "pre_tags": "<b style='color:red'>",  # 前缀
    "post_tags": "</b>"
  },
  "aggs": { # 查完后聚合
    "brandAgg": {
      "terms": {
        "field": "brandId",
        "size": 10
      },
      "aggs": { # 子聚合
        "brandNameAgg": {  # 每个商品id的品牌
          "terms": {
            "field": "brandName",
            "size": 10
          }
        },

        "brandImgAgg": {
          "terms": {
            "field": "brandImg",
            "size": 10
          }
        }

      }
    },
    "catalogAgg":{
      "terms": {
        "field": "catalogId",
        "size": 10
      },
      "aggs": {
        "catalogNameAgg": {
          "terms": {
            "field": "catalogName",
            "size": 10
          }
        }
      }
    },
    "attrs":{
      "nested": {"path": "attrs" },
      "aggs": {
        "attrIdAgg": {
          "terms": {
            "field": "attrs.attrId",
            "size": 10
          },
          "aggs": {
            "attrNameAgg": {
              "terms": {
                "field": "attrs.attrName",
                "size": 10
              }
            }
          }
        }
      }
    }
  }
}