当前位置 : 主页 > 编程语言 > java >

ElasticSearch-商品上架+商品查询

来源:互联网 收集:自由互联 发布时间:2023-03-22
public class EsConstant { //经常用的常量 抽取出来 static是全局的 可以让访问变得很方便,而且不会被修改。一般可以放配置信息,还有一些状态码的定义。 //其他的补充: static修饰的对象
public class EsConstant { //经常用的常量 抽取出来 static是全局的 可以让访问变得很方便,而且不会被修改。一般可以放配置信息,还有一些状态码的定义。 //其他的补充: static修饰的对象是放在引用的根下的,意味着几乎不会被回收 public static final String PRODUCT_INDEX ="product";//sku在es中索引 }

商品上架 传入 商品id 封装SkuEsModel upProducts 调用远程 searchFeignService.productStatusUp(upProducts); 商品上架 productStatusUp(List<SkuEsModel> skuEsModels)

@Override public Boolean productStatusUp(List<SkuEsModel> skuEsModels) throws IOException { //保存到es中 //1.建议es索引 product 建立映射关系 //bulk 批量操作 传入BulkRequest bulkRequest, RequestOptions options BulkRequest bulkRequest = new BulkRequest(); for (SkuEsModel model : skuEsModels) { //new 一个索引 保存product IndexRequest indexRequest = new IndexRequest(EsConstant.PRODUCT_INDEX); //指定唯一di indexRequest.id(model.getSkuId().toString()); String s = JSON.toJSONString(model); indexRequest.source(s, XContentType.JSON); bulkRequest.add(indexRequest); } BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, GulimallElasticSearchConfig.COMMON_OPTIONS); //todo 感知错误并处理 boolean b = bulk.hasFailures(); List<String> collect = Arrays.stream(bulk.getItems()).map(item -> { return item.getId(); }).collect(Collectors.toList()); log.info("商品上架wancheng:{},返回数据{}",collect,bulk.toString()); return b; }

查询检索

/** * @param param 传入SearchParam * @param model * @return 返回SearchReult */ @GetMapping({"/", "list.html"}) public String listPage(SearchParam param, Model model, HttpServletRequest request) { //HttpServletRequest 中有拿到前端传参路径 param.set_queryString(request.getQueryString()); //1. 根据传递来的页面的查询参数,去es中检索商品 SearchResult result =mallSearchService.search(param); model.addAttribute("result",result); return "list"; } @Override public SearchResult search(SearchParam param) { //动态构建DSL语句 SearchResult result = null;//返回 //1、准备检索请求 从新创建一个私有方法 SearchRequest searchRequest = buildSearchRequest(param); try { //2.执行检索请求 SearchResponse response = client.search(searchRequest, GulimallElasticSearchConfig.COMMON_OPTIONS); //3. 分析响应数据封装成我们需要的格式 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();//获取 命中的记录 ArrayList<SkuEsModel> esModels = new ArrayList<>(); //1、返回的所有查询到的商品 //命中hits的hits 不为空并且有数值 if (hits.getHits() != null && hits.getHits().length > 0) { //每一条命中的记录 for (SearchHit hit : hits.getHits()) { //得到命中中的_Source 以字符串形势 转换成SkuEsModell String sourceAsString = hit.getSourceAsString(); //用阿里巴巴JSON.parseObject 转换成SkuEsModel.class) SkuEsModel esModel = JSON.parseObject(sourceAsString, SkuEsModel.class); //判断是否按关键字检索,若是就显示高亮,否则不显示 if (!StringUtils.isEmpty(param.getKeyword())) { //拿到高亮信息显示标题 HighlightField skuTitle = hit.getHighlightFields().get("skuTitle"); String skuTitleValue = skuTitle.getFragments()[0].string(); esModel.setSkuTitle(skuTitleValue); } esModels.add(esModel); //定义ArrayList esModels放入集合中 } } result.setProducts(esModels); //4、当前商品涉及到的所有分类信息 List<SearchResult.AttrVo> attrVos = new ArrayList<>(); //获取属性信息的聚合 ParsedNested attrsAgg = response.getAggregations().get("attr_agg"); ParsedLongTerms attrIdAgg = attrsAgg.getAggregations().get("attr_id_agg"); for (Terms.Bucket bucket : attrIdAgg.getBuckets()) { SearchResult.AttrVo attrVo = new SearchResult.AttrVo(); //1、得到属性的id long attrId = bucket.getKeyAsNumber().longValue(); //2、得到属性的名字 ParsedStringTerms attrNameAgg = bucket.getAggregations().get("attr_name_agg"); String attrName = attrNameAgg.getBuckets().get(0).getKeyAsString(); //3、得到属性的所有值 ParsedStringTerms attrValueAgg = bucket.getAggregations().get("attr_value_agg"); List<String> attrValues = attrValueAgg.getBuckets().stream().map(item -> item.getKeyAsString()).collect(Collectors.toList()); attrVo.setAttrId(attrId); attrVo.setAttrName(attrName); attrVo.setAttrValue(attrValues); attrVos.add(attrVo); } result.setAttrs(attrVos); //3、当前商品涉及到的所有品牌信息 List<SearchResult.BrandVo> brandVos = new ArrayList<>(); //获取到品牌的聚合 ParsedLongTerms brandAgg = response.getAggregations().get("brand_agg"); for (Terms.Bucket bucket : brandAgg.getBuckets()) { SearchResult.BrandVo brandVo = new SearchResult.BrandVo(); //1、得到品牌的id 直接为数字并转换成long类型的 long brandId = bucket.getKeyAsNumber().longValue(); brandVo.setBrandId(brandId); //2、得到品牌的名字 ParsedStringTerms brandNameAgg = (ParsedStringTerms) bucket.getAggregations().get("brand_name_agg"); String brandName = brandNameAgg.getBuckets().get(0).getKeyAsString(); //3、得到品牌的图片 ParsedStringTerms brandImgAgg = (ParsedStringTerms) bucket.getAggregations().get("brand_img_agg"); String brandImg = brandImgAgg.getBuckets().get(0).getKeyAsString(); brandVo.setBrandImg(brandImg); brandVo.setBrandName(brandName); brandVos.add(brandVo); } result.setBrands(brandVos); //2、当前商品涉及到的所有属性信息 聚合的类型是 0=ParsedLongTerms@8429 直接转换ParsedLongTerms List<SearchResult.CatalogVo> catalogVos = new ArrayList<>(); ParsedLongTerms catalog_agg = response.getAggregations().get("catalog_agg");//拿到分类聚合信息.get 获取名字 List<? extends Terms.Bucket> buckets = catalog_agg.getBuckets(); //遍历buckets for (Terms.Bucket bucket : buckets) { //拿到分类的id 和分类的名字 SearchResult.CatalogVo catalogVo = new SearchResult.CatalogVo(); String keyAsString = bucket.getKeyAsString(); catalogVo.setCatalogId(Long.parseLong(keyAsString)); //得到分类名 子聚合 ParsedStringTerms catalogNameAgg = bucket.getAggregations().get("catalog_name_agg"); String catalog_name = catalogNameAgg .getBuckets().get(0).getKeyAsString(); catalogVo.setCatalogName(catalog_name); catalogVos.add(catalogVo); } result.setCatalogs(catalogVos); //===============以上可以从聚合信息中获取====================// //5、分页信息-页码 来源param result.setPageNum(param.getPageNum()); //总记录数 long total = hits.getTotalHits().value; //获取总记录数的value值 result.setTotal(total);//保存总记录数 //总页码 计算得到 中记录数/ 每页大小;先判断有没有余数 ==0 没有余数 int totalPages = (int) total % EsConstant.PRODUCT_PAGESIEZE == 0 ? (int) total / EsConstant.PRODUCT_PAGESIEZE : ((int) total / EsConstant.PRODUCT_PAGESIEZE + 1); result.setTotalPages(totalPages); //可遍历的页码 List<Integer> pageNavs = new ArrayList<>(); for (int i = 1; i <= totalPages; i++) { pageNavs.add(i); } result.setPageNavs(pageNavs); //6、构建面包屑导航 if (param.getAttrs() != null && param.getAttrs().size() > 0) { List<SearchResult.NavVo> collect = param.getAttrs().stream().map(attr -> { //1、分析每一个attrs传过来的参数值 SearchResult.NavVo navVo = new SearchResult.NavVo(); String[] s = attr.split("_"); navVo.setNavValue(s[1]); R r = productFeignService.attrInfo(Long.parseLong(s[0])); if (r.getCode() == 0) { AttrResponseVo data = r.getData("attr", new TypeReference<AttrResponseVo>() { }); navVo.setNavName(data.getAttrName()); } else { navVo.setNavName(s[0]); } //2、取消了这个面包屑以后,我们要跳转到哪个地方,将请求的地址url里面的当前置空 //拿到所有的查询条件,去掉当前 String encode = null; try { encode = URLEncoder.encode(attr,"UTF-8"); encode = encode.replace("+","%20"); //浏览器对空格的编码和Java不一样,差异化处理 } catch (UnsupportedEncodingException e) { e.printStackTrace(); } String replace = param.get_queryString().replace("&attrs=" + encode, ""); navVo.setLink("http://search.gulimall.com/list.html?" + replace); return navVo; }).collect(Collectors.toList()); result.setNavs(collect); } return result; } private SearchRequest buildSearchRequest(SearchParam param) { SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();//所有检索请求构建DSL语句 /** * 模糊匹配,过滤(按照属性,分类,品牌,价格区间,库存) */ //1.构建bool -must-query BoolQueryBuilder boolQuery = QueryBuilders.boolQuery(); //1.1 构建 must 判断 must 如果传过来keyword 不为空 构建must模糊匹配 if (!StringUtils.isEmpty(param.getKeyword())) { //在must中继续构建匹配match 按照名字[]和数值[param 传过来的]进行匹配 boolQuery.must(QueryBuilders.matchQuery("skuTitle", param.getKeyword())); } //1.2 构建 bool -must-filter //1.2.1 bool -must-filter-item 三级分类id if (param.getCatalog3Id() != null) { boolQuery.filter(QueryBuilders.termQuery("catalogId", param.getCatalog3Id())); } //1.2.2 bool -must-filter-items品牌id brandId id 判断brandId集合不为空 且大小大于0 if (param.getBrandId() != null && param.getBrandId().size() > 0) { boolQuery.filter(QueryBuilders.termsQuery("brandId", param.getBrandId())); } //1.2.3 属性查询 是嵌入式 if (param.getAttrs() != null && param.getAttrs().size() > 0) { //attr lattrs= 1_5寸:8寸&attrs=2_16G:8G for (String attrStr : param.getAttrs()) { BoolQueryBuilder nestedBoolQuery = QueryBuilders.boolQuery(); //先分割属性 String[] s = attrStr.split("_"); String attrId = s[0];//检索书属性id //在分割属属性里面的多个数值 attrValues 检索属性值 String[] attrValues = s[1].split(":"); nestedBoolQuery.must(QueryBuilders.termQuery("attrs.attrId", attrId)); nestedBoolQuery.must(QueryBuilders.termsQuery("attrs.attrValue", attrValues)); //是嵌入式 用nestedQuery 传入三个值 每一一个必须都得生成一个nested查询 NestedQueryBuilder nestedQuery = QueryBuilders.nestedQuery("attrs", nestedBoolQuery, ScoreMode.None); boolQuery.filter(nestedQuery); } } //1.2.4 按照是否有库存 如果getHasStock等于1 就是ture if (null != param.getHasStock()) { boolQuery.filter(QueryBuilders.termQuery("hasStock", param.getHasStock() == 1)); } //1.2. 按价格区间 if (!StringUtils.isEmpty(param.getSkuPrice())) { RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("skuPrice"); String[] s = param.getSkuPrice().split("_");//分割价格 //长度为2 是一个区间 if (s.length == 2 && s[0] != "") { //大于等于s[0] 第一个 小于等于s[1]第二个 rangeQuery.gte(null).lte(s[1]); } else if (s.length == 2) { //大于等于s[0] 第一个 小于等于s[1]第二个 rangeQuery.gte(s[0]).lte(s[1]); } else if (s.length == 1) { //如果长度等他1 是有两种情况 _500 和500_ if (param.getSkuPrice().startsWith("_")) { rangeQuery.lte(s[0]); } if (param.getSkuPrice().endsWith("_")) { rangeQuery.gte(s[0]); } } boolQuery.filter(rangeQuery); } //把以前的所有条件都拿来进行封装 sourceBuilder.query(boolQuery); /** * 排序,分页,高亮 */ //2.1 排序 if (!StringUtils.isEmpty(param.getSort())) { //sort=hostSore_asc/desc String[] s = param.getSort().split("_"); //构建排序 不区分大小写 SortOrder sortOrder = "asc".equalsIgnoreCase(s[1]) ? SortOrder.ASC : SortOrder.DESC; sourceBuilder.sort(s[0], sortOrder); } //2.2分页 //2.2.分页pageSize:5 // pageNum:1 from:0 size:5 [0,1,2,3,4] // pageNum:2 from:5 size:5 //from = (pageNum- 1)*size sourceBuilder.from((param.getPageNum() - 1) * EsConstant.PRODUCT_PAGESIEZE); sourceBuilder.size(EsConstant.PRODUCT_PAGESIEZE); //2.3 高亮设置 只有传入参数才计算 if (!StringUtils.isEmpty(param.getKeyword())) { HighlightBuilder builder = new HighlightBuilder(); builder.field("skuTitle");//设置哪个高亮 builder.preTags("<b style=color:red>"); builder.postTags("</b>"); sourceBuilder.highlighter(builder); } /** * 聚合分析 */ //品牌聚合 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"); catalog_agg.field("catalogId").size(20); catalog_agg.subAggregation(AggregationBuilders.terms("catalog_name_agg").field("catalogName").size(1)); sourceBuilder.aggregation(catalog_agg); //2. 按照属性信息进行聚合 嵌入聚合 NestedAggregationBuilder attr_agg = AggregationBuilders.nested("attr_agg", "attrs"); //2.1 按照属性ID进行聚合 子聚合 AggregationBuilders TermsAggregationBuilder attr_id_agg = AggregationBuilders.terms("attr_id_agg").field("attrs.attrId"); attr_agg.subAggregation(attr_id_agg); //2.1.1 子聚合的子聚合subAggregation attr_id_agg.subAggregation(AggregationBuilders.terms("attr_name_agg").field("attrs.attrName").size(1)); //2.1.1 在每个属性ID下,按照属性值进行聚合 attr_id_agg.subAggregation(AggregationBuilders.terms("attr_value_agg").field("attrs.attrValue").size(50)); sourceBuilder.aggregation(attr_agg); String s = sourceBuilder.toString(); System.out.println("构建DSL" + s); log.debug("构建的DSL语句 {}", sourceBuilder.toString()); SearchRequest searchRequest = new SearchRequest(new String[]{EsConstant.PRODUCT_INDEX}, sourceBuilder); return searchRequest; } }
上一篇:会话以及会话技术
下一篇:没有了
网友评论