请求参数封装对象如下
/**
* 封装页面所有可能传递进来的查询条件
* catalog3Id=225&keyword=小米&sort=saleCount_asc&hasStock=0/1&attrs
*/
@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;//排序条件
/**
* 过滤条件
* hasStock(是否有货) skuPrice(价格区间) brandId catalog3Id attrs
* hasStock=0/1;
* skuPrice=1_500/_500/500_
* brandId=1
*/
private Integer hasStock=1;// 是否只显示有货
private String skuPrice;//价格区间查询
private List<Long> brandId;//品牌id 可以多选
private List<String> attrs;//按照属性进行筛选
private Integer pageNum=1;
}
数据迁移代码如下
PUT gulimall_product
{
"mappings": {
"properties": {
"attrs": {
"type": "nested",
"properties": {
"attrId": {
"type": "long"
},
"attrName": {
"type": "keyword"
},
"attrValue": {
"type": "keyword"
}
}
},
"bandId": {
"type": "long"
},
"brandId": {
"type": "long"
},
"brandImg": {
"type": "keyword"},
"brandName": {
"type": "keyword"
},
"catalogId": {
"type": "long"
},
"catalogName": {
"type": "keyword"
},
"hasStock": {
"type": "boolean"
},
"hotScore": {
"type": "long"
},
"saleCount": {
"type": "long"
},
"skuId": {
"type": "long"
},
"skuImg": {
"type": "keyword"
},
"skuPrice": {
"type": "keyword"
},
"skuTitle": {
"type": "text",
"analyzer": "ik_smart"
},
"spuId": {
"type": "keyword"
}
}
}
}GET gulimall_product/_search
#迁移数据
POST _reindex
{
"source": {
"index": "product"
},
"dest": {
"index":"gulimall_product"
}
}
控制层请求如下
/**
* pringmvc将页面提交过来的全部参数封装成指定对象
* @param param
* @return
*/
@GetMapping("/list.html")
public String listPage(SearchParam param, Model model){
SearchResult result= mallSearchService.search(param);
model.addAttribute("result",result);
return "list";
}
请求封装思路如下
@Service public class MallSearchServiceImpl implements MallSearchService { @Autowired private RestHighLevelClient client; /** * 去es查 * @param param 检索的参数 * @return */ @Override public SearchResult search(SearchParam param) { //1.动态构建出查询需要的dsl语句 SearchResult result = new SearchResult(); //1.准备检索请求 SearchRequest searchRequest =buildSearchRequest(param); try { //2.执行检索请求 SearchResponse response = client.search(searchRequest, GulimallElasticSearchConfig.COMMON_OPTIONS); //3.分析响应数据封装成我们需要的格式 result = buildSearchResult(response) } catch (IOException e) { e.printStackTrace(); } return result; } /** * 准备检索请求 * @return */ private SearchRequest buildSearchRequest(SearchParam param) { } /** * 构建结果数据 * @param response * @return */ private SearchResult buildSearchResult(SearchResponse response) { } }
请求dsl语句api封装
/**
* 准备检索请求
*
* @return
*/
private SearchRequest buildSearchRequest(SearchParam param) {
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();//构建dsl语句
/**
* 查询:模糊匹配,过滤(按照属性,分类。品牌,价格区间,库存)
*/
//构建bool query
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
//1.1 must
if (!StringUtils.isEmpty(param.getKeyword())){
boolQuery.must(QueryBuilders.matchQuery("skuTitle",param.getKeyword()));
}
//1.2 bool filter --按照三级分类查询的
if (param.getCatalog3Id()!=null){
boolQuery.filter(QueryBuilders.termQuery("catalogId",param.getCatalog3Id()));
}
//1.32 bool filter -按照品牌id过滤
if (param.getBrandId()!=null&¶m.getBrandId().size()>0){
boolQuery.filter(QueryBuilders.termQuery("brandId",param.getBrandId()));
}
//1.2 bool filter -按照所有指定属性进行查询
if(param.getAttrs()!=null&¶m.getAttrs().size()>0){
//attrs=1_5寸:8寸
for (String attrStr : param.getAttrs()) {
BoolQueryBuilder nestedboolQuery = QueryBuilders.boolQuery();
String[] s = attrStr.split("_");
String attrId= s[0];//属性id
String[] attrValues = s[1].split(":");//属性值
nestedboolQuery.must(QueryBuilders.termQuery("attrs.attrId",attrId));
nestedboolQuery.must(QueryBuilders.termQuery("attrs.attrValue",attrValues));
NestedQueryBuilder nestedQuery = QueryBuilders.nestedQuery("attrs", nestedboolQuery, ScoreMode.None);
boolQuery.filter(nestedQuery);
}
}
//1.2 bool filter -按照库存是否有进行查询
boolQuery.filter(QueryBuilders.termQuery("hasStock",param.getHasStock()==1));
//1.2 bool filter -按照价格区间进行查询
if(!StringUtils.isEmpty(param.getSkuPrice())){
//1_500/_500/500_
RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("skuPrice");
String[] s = param.getSkuPrice().split("_");
if (s.length==2){
//区间
rangeQuery.gte(s[0]).lte(s[1]);
}else if (s.length==1){
if(param.getSkuPrice().startsWith("_")){
rangeQuery.lte(s[0]);
}else {
rangeQuery.gte(s[0]);
}
}
boolQuery.filter(rangeQuery);
}
//把以前的所有条件来进行封装
sourceBuilder.query(boolQuery);
/**
* 排序,分页,高亮
*/
//2.1 排序
if(!StringUtils.isEmpty(param.getSort())) {
String sort = param.getSort();
String[] s = sort.split("_");
SortOrder order=s[1].equalsIgnoreCase("asc")?SortOrder.ASC:SortOrder.DESC;
sourceBuilder.sort(s[0], order);
}
//2.2分页
//
sourceBuilder.from((param.getPageNum()-1)*EsConstant.PRODUCT_PAGESIZE);
sourceBuilder.size(EsConstant.PRODUCT_PAGESIZE);
//2.3 高亮 传keyword模糊匹配的时候
if (!StringUtils.isEmpty(param.getKeyword())){
HighlightBuilder builder = new HighlightBuilder();
builder.field("skuTitle");
builder.preTags("<b style='color:red'>");
builder.postTags("</b>");
sourceBuilder.highlighter(builder);
}
/**
* 聚合分析
*/
//1.品牌聚合
TermsAggregationBuilder brand_agg = AggregationBuilders.terms("brand_agg");
brand_agg.field("brandId").size(50);
//品牌聚合的子聚合
brand_agg.subAggregation(AggregationBuilders.terms("brand_name_agg").field("brandName").size(1));
brand_agg.subAggregation(AggregationBuilders.terms("brand_img_agg").field("brandImg").size(1));
sourceBuilder.aggregation(brand_agg);
//2.分类聚合
TermsAggregationBuilder catalog_agg = AggregationBuilders.terms("catalog_agg").field("catalogId").size(20);
catalog_agg.subAggregation(AggregationBuilders.terms("catalog_name_agg").field("catalogName").size(1));
sourceBuilder.aggregation(catalog_agg);
//3.属性聚合attr_agg
NestedAggregationBuilder attr_agg = AggregationBuilders.nested("attr_agg", "attrs");
//聚合出当前所有的attrId
TermsAggregationBuilder attr_id_agg = AggregationBuilders.terms("attr_id_agg").field("attrs.attrId");
//聚合分析出当前attr_id对应的名字
attr_id_agg.subAggregation(AggregationBuilders.terms("attr_name_agg").field("attrs.attrName").size(1));
//聚合分析出当前attr_id对应的所有可能的属性值
attr_id_agg.subAggregation(AggregationBuilders.terms("attr_value_agg").field("attrs.attValue").size(50));
attr_agg.subAggregation(attr_id_agg);
//聚合attr
sourceBuilder.aggregation(attr_agg);
System.out.println(sourceBuilder.toString());
SearchRequest searchRequest = new SearchRequest(new String[]{EsConstant.PRODUCT_INDEX},sourceBuilder);
return searchRequest;
}