Day414&415&416.检索服务 -谷粒商城
Posted 阿昌喜欢吃黄桃
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Day414&415&416.检索服务 -谷粒商城相关的知识,希望对你有一定的参考价值。
检索服务
0、准备环境
achangmall-search
- 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
- 配置
spring:
thymeleaf:
cache: false
- 放入页面
- 在index.html整合thymeleaf
<html lang="en" xmlns:th="http:/www.thymeleaf.org">
- 将静态资源放入nginx中,创建search文件夹
- 在index.html修改路径加上
/static/search/
- 配置window转发:C:\\Windows\\System32\\drivers\\etc\\hosts
- 阿昌项目启动报错: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
/**
* sort=saleCount_asc/desc
* sort=skuPrice_asc/desc
* sort=hotScore_asc/desc
*/
private String sort;//排序条件
private Integer hasStock;//是否只显示有货
private String skuPrice;//加个区间查询
private List<Long> brandId;//品牌id,可多选
private List<String> attrs;//按照属性筛选
private Integer pageNum = 1;//页码
}
检索结果VO
查询得到商品、总记录数、总页码
品牌list用于在品牌栏显示,分类list用于在分类栏显示
其他栏每栏用AttrVo表示
不仅要根据关键字从es中检索到商品
还要通过聚合生成品牌等信息,方便分类栏显示
- 检索结果VO
//检索返回页面Bean
@Data
public class SearchResult {
private List<SkuEsModel> products;//ES数据结构查询到的商品信息
private Integer pageNum;//当前页码
private Long total;//总记录数
private Integer totalPage;//总页码
private List<BrandVo> brandVos;//当前查询涉及到的品牌信息
private List<AttrVo> attrVos;//当前查询涉及到的属性信息
private List<CatalogVo> 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<String> attrValues;
}
}
- com.achang.achangmall.search.controller.SearchController
@Controller
public class SearchController {
@Autowired
MallSearchService mallSearchService;
@GetMapping("/list.html")
public String listPage(SearchParam param, Model model ){
SearchResult result = mallSearchService.search(param);
model.addAttribute("result",result);
return "list";
}
}
- com.achang.achangmall.search.service.impl.MallSearchServiceImpl
package com.achang.achangmall.search.service.impl;
import com.achang.achangmall.search.conf.ElasticsearchConfig;
import com.achang.achangmall.search.constant.ESConstant;
import com.achang.achangmall.search.service.MallSearchService;
import com.achang.achangmall.search.vo.SearchParam;
import com.achang.achangmall.search.vo.SearchResult;
import com.achang.common.to.es.SkuEsModel;
import com.alibaba.fastjson.JSON;
import org.apache.lucene.search.join.ScoreMode;
import org.apache.lucene.util.QueryBuilder;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.NestedQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.nested.NestedAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.nested.ParsedNested;
import org.elasticsearch.search.aggregations.bucket.terms.*;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import javax.swing.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/******
@author 阿昌
@create 2021-10-08 21:55
*******
*/
@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,param);
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
//构建结果数据
private SearchResult buildSearchResult(SearchResponse response,SearchParam param) {
SearchResult result = new SearchResult();
SearchHits hits = response.getHits();
SearchHit[] hitsHits = hits.getHits();//命中数据
//查询到的所有商品
List<SkuEsModel> products = new ArrayList<>(hitsHits.length);
if (!StringUtils.isEmpty(hitsHits)&&hitsHits.length>0){
for (SearchHit hitsHit : hitsHits) {
String sourceAsString = hitsHit.getSourceAsString();
SkuEsModel skuEsModel = JSON.parseObject(sourceAsString, SkuEsModel.class);
HighlightField skuTitle = hitsHit.getHighlightFields().get("skuTitle");
if (!StringUtils.isEmpty(param.getKeyword())){
skuEsModel.setSkuTitle(skuTitle.getFragments()[0].toString());//设置高亮text
}
products.add(skuEsModel);
}
}
result.setProducts(products);
//商品所涉及到的所有属性信息
ParsedLongTerms catalog_agg = response.getAggregations().get("catalog_agg");
List<? extends Terms.Bucket> buckets = catalog_agg.getBuckets();
List<SearchResult.CatalogVo> catalogVos = new ArrayList<>(buckets.size());
for (Terms.Bucket bucket : buckets) {
SearchResult.CatalogVo catalogVo = new SearchResult.CatalogVo();
ParsedStringTerms catalog_name_agg = bucket.getAggregations().get("catalog_name_agg");
catalogVo.setCatalogName(catalog_name_agg.getBuckets().get(0).getKeyAsString());
catalogVo.setCatalogId((int) Long.parseLong(bucket.getKeyAsString()));
catalogVos.add(catalogVo);
}
result.setCatalogVos(catalogVos);
//商品所涉及到所有的品牌信息
ParsedLongTerms brand_agg = response.getAggregations().get("brand_agg");
List<? extends Terms.Bucket> brandAggBuckets = brand_agg.getBuckets();
List<SearchResult.BrandVo> brandVos = new ArrayList<>(brandAggBuckets.size());
for (Terms.Bucket brandAggBucket : brandAggBuckets) {
SearchResult.BrandVo brandVo = new SearchResult.BrandVo();
ParsedStringTerms brand_img_agg = brandAggBucket.getAggregations().get("brand_img_agg");
ParsedStringTerms brand_name_agg = brandAggBucket.getAggregations().get("brand_name_agg");
brandVo.setBrandName(brand_name_agg.getBuckets().get(0).getKeyAsString());
brandVo.setBrandImg(brand_img_agg.getBuckets().get(0).getKeyAsString());
brandVo.setBrandId((int) brandAggBucket.getKeyAsNumber().longValue());
brandVos.add(brandVo);
}
result.setBrandVos(brandVos);
//当前商品所及到所有的属性信息
ParsedNested attr_agg = response.getAggregations().get("attr_agg");
ParsedLongTerms attr_id_agg = attr_agg.getAggregations().get("attr_id_agg");
List<? extends Terms.Bucket> attrIdAggBuckets = attr_id_agg.getBuckets();
List<SearchResult.AttrVo> attrVos = new ArrayList<>(attrIdAggBuckets.size());
for (Terms.Bucket attrIdAggBucket : attrIdAggBuckets) {
SearchResult.AttrVo attrVo = new SearchResult.AttrVo();
int id = attrIdAggBucket.getKeyAsNumber().intValue();
ParsedStringTerms attr_name_agg = attrIdAggBucket.getAggregations().get("attr_name_agg");
String attrName = attr_name_agg.getBuckets().get(0).getKeyAsString();
ParsedStringTerms attr_value_agg = attrIdAggBucket.getAggregations().get("attr_value_agg");
List<? extends Terms.Bucket> value_aggBuckets = attr_value_agg.getBuckets();
ArrayList<String> attrValueList = new <以上是关于Day414&415&416.检索服务 -谷粒商城的主要内容,如果未能解决你的问题,请参考以下文章