achangmall-search
- 引入依赖
org.springframework.boot spring-boot-starter-thymeleaf org.springframework.boot spring-boot-devtools
- 配置
spring:
thymeleaf:
cache: false
- 放入页面
- 在index.html整合thymeleaf
- 将静态资源放入nginx中,创建search文件夹
- 在index.html修改路径加上/static/search/
- 配置window转发:C:WindowsSystem32driversetchosts
- 阿昌项目启动报错:redisson io.netty.channel.epoll.EpollEventLoopGroup
解决方案:移除之前redisson配置文件中的
config.setTransportMode(TransportMode.EPOLL);
- 配置nginx转发这search服务
- 配置gateway,转发到search服务
- id: nginx_route
uri: lb://achangmall-product
predicates:
- Host=achangmall.com
- id: search_route
uri: lb://achangmall-search
predicates:
- Host=search.achangmall.com
- 整体的流程
请求search.achangmall.com被nginx转发给gateway转发给search服务
- 重启各个服务,测试访问search.achangmall.com,是否会被2次转发到search服务
成功!!!!
- 修改html.html为list.html
- 页面跳转的控制器com.achang.achangmall.search.controller.SearchController
@Controller
public class SearchController {
@GetMapping("/list.html")
public String listPage(){
return "list";
}
}
- 修改achangmall-product/src/main/resources/templates/index.html
- 修改/mydata/nginx/html/static/index/js/catalogLoader.js
跳转域名修改为你设置的域名
- 测试搜索框搜索,是否跳转,成功
检索参数VO与url
- 全文检索:skuTitle-》keyword
- 排序:saleCount(销量)、hotScore(热度分)、skuPrice(价格)
- 过滤:hasStock、skuPrice区间、brandId、catalog3Id、attrs
- 聚合:attrs
keyword=小米& sort=saleCount_desc/asc& hasStock=0/1& skuPrice=400_1900& brandId=1& catalog3Id=1& attrs=1_3G:4G:5G& attrs=2_骁龙845& attrs=4_高清屏
- 创建SearchParam用于检索VO
//页面检索条件
@Data
public class SearchParam {
private String keyword;//全文匹配关键字
private Long catalog3Id;//三级分类id
private String sort;//排序条件
private Integer hasStock;//是否只显示有货
private String skuPrice;//加个区间查询
private List brandId;//品牌id,可多选
private List attrs;//按照属性筛选
private Integer pageNum;//页码
}
检索结果VO
查询得到商品、总记录数、总页码
品牌list用于在品牌栏显示,分类list用于在分类栏显示
其他栏每栏用AttrVo表示
不仅要根据关键字从es中检索到商品
还要通过聚合生成品牌等信息,方便分类栏显示
- 检索结果VO
//检索返回页面Bean
@Data
public class SearchResult {
private List products;//ES数据结构查询到的商品信息
private Integer pageNum;//当前页码
private Long total;//总记录数
private Integer totalPage;//总页码
private List brandVos;//当前查询涉及到的品牌信息
private List attrVos;//当前查询涉及到的属性信息
private List catalogVos;//当前查询涉及到的分类信息
//=========以上返给页面的信息=============
//品牌vo对象
public static class BrandVo{
private Integer brandId;
private String brandName;
private String brandImg;
}
//分类vo对象
public static class CatalogVo{
private Integer catalogId;
private String catalogName;
}
//属性vo对象
public static class AttrVo{
private Integer attrId;
private String attrName;
private List attrValues;
}
}
- com.achang.achangmall.search.controller.SearchController
@Controller
public class SearchController {
@Autowired
MallSearchService mallSearchService;
@GetMapping("/list.html")
public String listPage(@RequestParam SearchParam param, Model model ){
SearchResult result = mallSearchService.search(param);
model.addAttribute("result",result);
return "list";
}
}
- com.achang.achangmall.search.service.impl.MallSearchServiceImpl
@Service
public class MallSearchServiceImpl implements MallSearchService {
@Resource
private RestHighLevelClient client;
@Override
public SearchResult search(SearchParam param) {
SearchResult result = null;
SearchRequest request = buildSearchRequest(param);
try {
SearchResponse response = client.search(request, ElasticsearchConfig.COMMON_OPTIONS);
result = buildSearchResult(response);
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
//构建结果数据
private SearchResult buildSearchResult(SearchResponse response) {
return null;
}
//准备检索请求
private SearchRequest buildSearchRequest(SearchParam param) {
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//构建dsl语句
//查询条件
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
String keyword = param.getKeyword();
if (!StringUtils.isEmpty(keyword)){
boolQueryBuilder.must(QueryBuilders.matchQuery("skuTitle",keyword));
}
Long catalog3Id = param.getCatalog3Id();
if (!StringUtils.isEmpty(catalog3Id)){
boolQueryBuilder.filter(QueryBuilders.termQuery("catalogId",catalog3Id));
}
List brandId = param.getBrandId();
if (!StringUtils.isEmpty(brandId) && brandId.size()>0){
boolQueryBuilder.filter(QueryBuilders.termsQuery("brandId",brandId));
}
Integer hasStock = param.getHasStock();
boolQueryBuilder.filter(QueryBuilders.termQuery("hasStock",hasStock==1));
List attrs = param.getAttrs();
if (!StringUtils.isEmpty(attrs)&&attrs.size()>0){
for (String attr : attrs) {
BoolQueryBuilder nestedBootQuery = QueryBuilders.boolQuery();
String[] attrStr = attr.split("_");
String attrId = attrStr[0];
String[] attrValues = attrStr[1].split(":");
nestedBootQuery.must(QueryBuilders.termQuery("attrs.attrId",attrId));
nestedBootQuery.must(QueryBuilders.termsQuery("attrs.attrValue",attrValues));
NestedQueryBuilder nestedQuery = QueryBuilders.nestedQuery("attrs", nestedBootQuery, ScoreMode.None);
boolQueryBuilder.filter(nestedQuery);
}
}
String skuPrice = param.getSkuPrice();
if (!StringUtils.isEmpty(skuPrice)){
RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("skuPrice");
String[] strArr = skuPrice.split("_");
if (strArr.length==2){
rangeQuery.gte(strArr[0]).lte(strArr[1]);
}else if (strArr.length==1){
if (skuPrice.startsWith("_")){
rangeQuery.lte(strArr[1]);
}
if (skuPrice.endsWith("_")){
rangeQuery.gte(strArr[0]);
}
}
boolQueryBuilder.filter(rangeQuery);
}
searchSourceBuilder.query(boolQueryBuilder);
//排序,分页,高亮
//聚合分析
SearchRequest request = new SearchRequest(new String[]{ESConstant.PRODUCT_INDEX},searchSourceBuilder);
return request;
}
}
明天继续!!!



