赞
踩
官网文档:Maven Repository | Java REST Client [7.17] | Elastic
SpringBoot默认引入了其他的ES包,在此替换为自己想要的
<properties>
<java.version>1.8</java.version>
<elasticsearch.version>7.17.7</elasticsearch.version>
</properties>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.17.7</version>
</dependency>
/** * 1 导入依赖 * 2 编写配置 给容器中注入一个RestHighLevelClient * 3 参API */ @Configuration public class GulimallElasticSearchConfig { public static final RequestOptions COMMON_OPTIONS; static { RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); // builder.addHeader("Authorization", "Bearer " + TOKEN); // builder.setHttpAsyncResponseConsumerFactory( // new HttpAsyncResponseConsumerFactory // .HeapBufferedResponseConsumerFactory(30 * 1024 * 1024 * 1024)); COMMON_OPTIONS = builder.build(); } @Bean public RestHighLevelClient esRestClient() { RestClientBuilder builder = RestClient.builder( new HttpHost("localhost", 9200, "http") // new HttpHost("localhost", 9201, "http") ); RestHighLevelClient client = new RestHighLevelClient(builder); return client; } }
接口文档:Index API | Java REST Client [7.17] | Elastic
插入API
@Slf4j @Service public class ProductServiceImpl implements ProductService { @Autowired RestHighLevelClient restHighLevelClient; @Override public boolean productStatusUp(List<SkuEsModel> skuEsModels) throws IOException { //将数据保存带es中 //1 给es中建立索引 product 建立好映射关系 //2 保存数据到es中 BulkRequest bulkRequest = new BulkRequest(); for (SkuEsModel skuEsModel : skuEsModels) { //放到哪个索引? IndexRequest indexRequest = new IndexRequest("product"); indexRequest.id(skuEsModel.getSkuId().toString()); String jsonString = JSON.toJSONString(skuEsModel); indexRequest.source(jsonString, 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("商品上架完成:{},返回数据:{}", collect, bulk.toString()); return b; } }
查询API
@Slf4j @Service public class MallSearchServiceImpl implements MallSearchService { @Autowired RestHighLevelClient restHighLevelClient; @Autowired ProductFeignService productFeignService; @Override // service public SearchResult searchResult(SearchParam searchParam) {//根据带来的请求内容封装 SearchResult searchResult= null; // 通过请求参数构建查询请求 SearchRequest request = bulidSearchRequest(searchParam); try { SearchResponse searchResponse = restHighLevelClient.search(request, GulimallElasticSearchConfig.COMMON_OPTIONS); // 将es响应数据封装成结果 searchResult = bulidSearchResult(searchParam,searchResponse); } catch (IOException e) { e.printStackTrace(); } return searchResult; } private SearchRequest bulidSearchRequest(SearchParam searchParam) { // 用于构建DSL语句 SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); //1. 构建bool query BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder(); //1.1 bool must if (!StringUtils.isEmpty(searchParam.getKeyword())) { boolQueryBuilder.must(QueryBuilders.matchQuery("skuTitle", searchParam.getKeyword())); } //1.2 bool filter //1.2.1 catalog if (searchParam.getCatalog3Id()!=null){ boolQueryBuilder.filter(QueryBuilders.termQuery("catalogId", searchParam.getCatalog3Id())); } //1.2.2 brand if (searchParam.getBrandId()!=null&&searchParam.getBrandId().size()>0) { boolQueryBuilder.filter(QueryBuilders.termsQuery("brandId",searchParam.getBrandId())); } //1.2.3 hasStock if (searchParam.getHasStock() != null) { boolQueryBuilder.filter(QueryBuilders.termQuery("hasStock", searchParam.getHasStock() == 1)); } //1.2.4 priceRange RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("skuPrice"); if (!StringUtils.isEmpty(searchParam.getSkuPrice())) { String[] prices = searchParam.getSkuPrice().split("_"); if (prices.length == 1) { if (searchParam.getSkuPrice().startsWith("_")) { rangeQueryBuilder.lte(Integer.parseInt(prices[0])); }else { rangeQueryBuilder.gte(Integer.parseInt(prices[0])); } } else if (prices.length == 2) { //_6000会截取成["","6000"] if (!prices[0].isEmpty()) { rangeQueryBuilder.gte(Integer.parseInt(prices[0])); } rangeQueryBuilder.lte(Integer.parseInt(prices[1])); } boolQueryBuilder.filter(rangeQueryBuilder); } //1.2.5 attrs-nested //attrs=1_5寸:8寸&2_16G:8G List<String> attrs = searchParam.getAttrs(); BoolQueryBuilder queryBuilder = new BoolQueryBuilder(); if (attrs!=null&&attrs.size() > 0) { attrs.forEach(attr->{ String[] attrSplit = attr.split("_"); queryBuilder.must(QueryBuilders.termQuery("attrs.attrId", attrSplit[0])); String[] attrValues = attrSplit[1].split(":"); queryBuilder.must(QueryBuilders.termsQuery("attrs.attrValue", attrValues)); }); } NestedQueryBuilder nestedQueryBuilder = QueryBuilders.nestedQuery("attrs", queryBuilder, ScoreMode.None); boolQueryBuilder.filter(nestedQueryBuilder); //1.X bool query构建完成 searchSourceBuilder.query(boolQueryBuilder); //2. sort eg:sort=saleCount_desc/asc if (!StringUtils.isEmpty(searchParam.getSort())) { String[] sortSplit = searchParam.getSort().split("_"); searchSourceBuilder.sort(sortSplit[0], sortSplit[1].equalsIgnoreCase("asc") ? SortOrder.ASC : SortOrder.DESC); } //3. 分页 // 是检测结果分页 searchSourceBuilder.from((searchParam.getPageNum() - 1) * EsConstant.PRODUCT_PAGESIZE); searchSourceBuilder.size(EsConstant.PRODUCT_PAGESIZE); //4. 高亮highlight if (!StringUtils.isEmpty(searchParam.getKeyword())) { HighlightBuilder highlightBuilder = new HighlightBuilder(); highlightBuilder.field("skuTitle"); highlightBuilder.preTags("<b style='color:red'>"); highlightBuilder.postTags("</b>"); searchSourceBuilder.highlighter(highlightBuilder); } //5. 聚合 //5.1 按照brand聚合 TermsAggregationBuilder brandAgg = AggregationBuilders.terms("brandAgg").field("brandId"); TermsAggregationBuilder brandNameAgg = AggregationBuilders.terms("brandNameAgg").field("brandName"); TermsAggregationBuilder brandImgAgg = AggregationBuilders.terms("brandImgAgg").field("brandImg"); brandAgg.subAggregation(brandNameAgg); brandAgg.subAggregation(brandImgAgg); searchSourceBuilder.aggregation(brandAgg); //5.2 按照catalog聚合 TermsAggregationBuilder catalogAgg = AggregationBuilders.terms("catalogAgg").field("catalogId"); // 子聚合 TermsAggregationBuilder catalogNameAgg = AggregationBuilders.terms("catalogNameAgg").field("catalogName"); catalogAgg.subAggregation(catalogNameAgg); searchSourceBuilder.aggregation(catalogAgg); //5.3 按照attrs聚合 NestedAggregationBuilder nestedAggregationBuilder = new NestedAggregationBuilder("attrs", "attrs"); //按照attrId聚合 //按照attrId聚合之后再按照attrName和attrValue聚合 TermsAggregationBuilder attrIdAgg = AggregationBuilders.terms("attrIdAgg" ).field("attrs.attrId"); TermsAggregationBuilder attrNameAgg = AggregationBuilders.terms("attrNameAgg" ).field("attrs.attrName"); TermsAggregationBuilder attrValueAgg = AggregationBuilders.terms("attrValueAgg").field("attrs.attrValue"); attrIdAgg.subAggregation(attrNameAgg); attrIdAgg.subAggregation(attrValueAgg); nestedAggregationBuilder.subAggregation(attrIdAgg); searchSourceBuilder.aggregation(nestedAggregationBuilder); log.debug("构建的DSL语句 {}",searchSourceBuilder.toString()); SearchRequest request = new SearchRequest(new String[]{EsConstant.PRODUCT_INDEX}, searchSourceBuilder); return request; } private SearchResult bulidSearchResult(SearchParam searchParam, SearchResponse searchResponse) { SearchResult result = new SearchResult(); SearchHits hits = searchResponse.getHits(); //1. 封装查询到的商品信息 if (hits.getHits()!=null&&hits.getHits().length>0){ List<SkuEsModel> skuEsModels = new ArrayList<>(); for (SearchHit hit : hits) { String sourceAsString = hit.getSourceAsString(); SkuEsModel skuEsModel = JSON.parseObject(sourceAsString, SkuEsModel.class); //设置高亮属性 if (!StringUtils.isEmpty(searchParam.getKeyword())) { HighlightField skuTitle = hit.getHighlightFields().get("skuTitle"); String highLight = skuTitle.getFragments()[0].string(); skuEsModel.setSkuTitle(highLight); } skuEsModels.add(skuEsModel); } result.setProduct(skuEsModels); } //2. 封装分页信息 //2.1 当前页码 result.setPageNum(searchParam.getPageNum()); //2.2 总记录数 long total = hits.getTotalHits().value; result.setTotal(total); //2.3 总页码 Integer totalPages = (int)total % EsConstant.PRODUCT_PAGESIZE == 0 ? (int)total / EsConstant.PRODUCT_PAGESIZE : (int)total / EsConstant.PRODUCT_PAGESIZE + 1; result.setTotalPages(totalPages); List<Integer> pageNavs = new ArrayList<>(); for (int i = 1; i <= totalPages; i++) { pageNavs.add(i); } result.setPageNavs(pageNavs); //3. 查询结果涉及到的品牌 List<SearchResult.BrandVo> brandVos = new ArrayList<>(); Aggregations aggregations = searchResponse.getAggregations(); //ParsedLongTerms用于接收terms聚合的结果,并且可以把key转化为Long类型的数据 ParsedLongTerms brandAgg = aggregations.get("brandAgg"); for (Terms.Bucket bucket : brandAgg.getBuckets()) { //3.1 得到品牌id Long brandId = bucket.getKeyAsNumber().longValue(); Aggregations subBrandAggs = bucket.getAggregations(); //3.2 得到品牌图片 ParsedStringTerms brandImgAgg=subBrandAggs.get("brandImgAgg"); String brandImg = brandImgAgg.getBuckets().get(0).getKeyAsString(); //3.3 得到品牌名字 Terms brandNameAgg=subBrandAggs.get("brandNameAgg"); String brandName = brandNameAgg.getBuckets().get(0).getKeyAsString(); SearchResult.BrandVo brandVo = new SearchResult.BrandVo(brandId, brandName, brandImg); brandVos.add(brandVo); } result.setBrands(brandVos); //4. 查询涉及到的所有分类 List<SearchResult.CatalogVo> catalogVos = new ArrayList<>(); ParsedLongTerms catalogAgg = aggregations.get("catalogAgg"); for (Terms.Bucket bucket : catalogAgg.getBuckets()) { //4.1 获取分类id Long catalogId = bucket.getKeyAsNumber().longValue(); Aggregations subcatalogAggs = bucket.getAggregations(); //4.2 获取分类名 ParsedStringTerms catalogNameAgg=subcatalogAggs.get("catalogNameAgg"); String catalogName = catalogNameAgg.getBuckets().get(0).getKeyAsString(); SearchResult.CatalogVo catalogVo = new SearchResult.CatalogVo(catalogId, catalogName); catalogVos.add(catalogVo); } result.setCatalogs(catalogVos); //5 查询涉及到的所有属性 List<SearchResult.AttrVo> attrVos = new ArrayList<>(); //ParsedNested用于接收内置属性的聚合 ParsedNested parsedNested=aggregations.get("attrs"); ParsedLongTerms attrIdAgg=parsedNested.getAggregations().get("attrIdAgg"); for (Terms.Bucket bucket : attrIdAgg.getBuckets()) { //5.1 查询属性id Long attrId = bucket.getKeyAsNumber().longValue(); Aggregations subAttrAgg = bucket.getAggregations(); //5.2 查询属性名 ParsedStringTerms attrNameAgg=subAttrAgg.get("attrNameAgg"); String attrName = attrNameAgg.getBuckets().get(0).getKeyAsString(); //5.3 查询属性值 ParsedStringTerms attrValueAgg = subAttrAgg.get("attrValueAgg"); List<String> attrValues = new ArrayList<>(); for (Terms.Bucket attrValueAggBucket : attrValueAgg.getBuckets()) { String attrValue = attrValueAggBucket.getKeyAsString(); attrValues.add(attrValue); List<SearchResult.NavVo> navVos = new ArrayList<>(); } SearchResult.AttrVo attrVo = new SearchResult.AttrVo(attrId, attrName, attrValues); attrVos.add(attrVo); } result.setAttrs(attrVos); // 6. 构建面包屑导航 List<String> attrs = searchParam.getAttrs(); if (attrs != null && attrs.size() > 0) { List<SearchResult.NavVo> navVos = attrs.stream().map(attr -> { String[] split = attr.split("_"); SearchResult.NavVo navVo = new SearchResult.NavVo(); //6.1 设置属性值 navVo.setNavValue(split[1]); //6.2 查询并设置属性名 try { R r = productFeignService.attrInfo(Long.parseLong(split[0])); if (r.getCode() == 0) { AttrResponseVo attrResponseVo = JSON.parseObject(JSON.toJSONString(r.get("attr")), new TypeReference<AttrResponseVo>() { }); navVo.setNavName(attrResponseVo.getAttrName()); } } catch (Exception e) { log.error("远程调用商品服务查询属性失败", e); } //6.3 设置面包屑跳转链接 String queryString = searchParam.get_queryString(); String replace = queryString.replace("&attrs=" + attr, "").replace("attrs=" + attr+"&", "").replace("attrs=" + attr, ""); navVo.setLink("http://search.gulimall.com/index.html" + (replace.isEmpty()?"":"?"+replace)); return navVo; }).collect(Collectors.toList()); result.setNavs(navVos); } return result; } }
版本对应关系:Spring Data Elasticsearch - Reference Documentation
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency>
@ConfigurationProperties(prefix = "elasticsearch") @Configuration @Data public class ElasticsearchConfig extends AbstractElasticsearchConfiguration { private String host ; private Integer port ; //重写父类方法 @Override public RestHighLevelClient elasticsearchClient() { RestClientBuilder builder = RestClient.builder(new HttpHost(host, port)); RestHighLevelClient restHighLevelClient = new RestHighLevelClient(builder); return restHighLevelClient; } }
@Repository
public interface ProductDao extends ElasticsearchRepository<Product,Long> {
}
@RunWith(SpringRunner.class) @SpringBootTest public class SpringDataESIndexTest { @Autowired private ElasticsearchRestTemplate elasticsearchRestTemplate; @Autowired private ProductDao productDao; @Test public void deleteIndex(){ //创建索引,系统初始化会自动创建索引 boolean flg = elasticsearchRestTemplate.deleteIndex(Product.class); System.out.println("删除索引 = " + flg); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。