请求参数封装对象如下
/**
* 封装页面所有可能传递进来的查询条件
* 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; }