营销型网站建设的特点,佛山市南海区城乡建设局网站,广告设计公司市场专员,资源网站优化排名优化本系列文章主要介绍基于 Spring Data Elasticsearch 实现商品搜索的后端代码#xff0c;介绍代码逻辑和代码实现。 主要实现功能#xff1a;根据搜索关键字查询、条件筛选、规格过滤、价格区间搜索、搜索查询分页、搜索查询排序、高亮查询。
主要应用技术:canal#xff0c;…本系列文章主要介绍基于 Spring Data Elasticsearch 实现商品搜索的后端代码介绍代码逻辑和代码实现。 主要实现功能根据搜索关键字查询、条件筛选、规格过滤、价格区间搜索、搜索查询分页、搜索查询排序、高亮查询。
主要应用技术:canalEureka微服务架构Microservices ArchitectureSpring Data Elasticsearch
一、 搜索分页
1 分页分析
基于spring data ElasticSearch 对于查询结果进行分页操作。 页面需要实现分页搜索所以我们后台每次查询的时候需要实现分页。用户页面每次会传入当前页和每页查询多少条数据当然如果不传入每页显示多少条数据设置默认查询条即可。
2 分页实现
分页使用PageRequest.of( pageNo- 1, pageSize);实现第1个参数表示第N页从0开始第2个参数表示每页显示多少条实现代码如下 代码如下
Overridepublic Map search(MapString, String searchMap) throws Exception {MapString, Object resultMap new HashMap();
//有条件才查询Esif (null ! searchMap) {//组合条件对象BoolQueryBuilder boolQuery QueryBuilders.boolQuery();//0:关键词if (!StringUtils.isEmpty(searchMap.get(keywords))) {boolQuery.must(QueryBuilders.matchQuery(name, searchMap.get(keywords)).operator(Operator.AND));}//1:条件 品牌if (!StringUtils.isEmpty(searchMap.get(brand))) {boolQuery.filter(QueryBuilders.termQuery(brandName, searchMap.get(brand)));}
//2:条件 规格for (String key : searchMap.keySet()) {if (key.startsWith(spec_)) {String value searchMap.get(key).replace(%2B, );boolQuery.filter(QueryBuilders.termQuery(specMap. key.substring(5) .keyword,value));}}//3:条件 价格if (!StringUtils.isEmpty(searchMap.get(price))) {String[] p searchMap.get(price).split(-);boolQuery.filter(QueryBuilders.rangeQuery(price).gte(p[0]));if (p.length 2) {boolQuery.filter(QueryBuilders.rangeQuery(price).lte(p[1]));}}
//4. 原生搜索实现类NativeSearchQueryBuilder nativeSearchQueryBuilder new NativeSearchQueryBuilder();nativeSearchQueryBuilder.withQuery(boolQuery);
//6. 品牌聚合(分组)查询String skuBrand skuBrand;nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms(skuBrand).field(brandName));
//7. 规格聚合(分组)查询String skuSpec skuSpec;nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms(skuSpec).field(spec.keyword));
String pageNum searchMap.get(pageNum);if (null pageNum) {pageNum 1;}//9: 分页nativeSearchQueryBuilder.withPageable(PageRequest.of(Integer.parseInt(pageNum) - 1, Page.pageSize));
//10: 执行查询, 返回结果对象AggregatedPageSkuInfo aggregatedPage esTemplate.queryForPage(nativeSearchQueryBuilder.build(), SkuInfo.class, new SearchResultMapper() {Overridepublic T AggregatedPageT mapResults(SearchResponse searchResponse, ClassT aClass, Pageable pageable) {
ListT list new ArrayList();
SearchHits hits searchResponse.getHits();if (null ! hits) {for (SearchHit hit : hits) {SkuInfo skuInfo JSON.parseObject(hit.getSourceAsString(), SkuInfo.class);
list.add((T) skuInfo);}}return new AggregatedPageImplT(list, pageable, hits.getTotalHits(), searchResponse.getAggregations());}});
//11. 总条数resultMap.put(total, aggregatedPage.getTotalElements());//12. 总页数resultMap.put(totalPages, aggregatedPage.getTotalPages());//13. 查询结果集合resultMap.put(rows, aggregatedPage.getContent());
//14. 获取品牌聚合结果StringTerms brandTerms (StringTerms) aggregatedPage.getAggregation(skuBrand);ListString brandList brandTerms.getBuckets().stream().map(bucket - bucket.getKeyAsString()).collect(Collectors.toList());resultMap.put(brandList, brandList);
//15. 获取规格聚合结果StringTerms specTerms (StringTerms) aggregatedPage.getAggregation(skuSpec);ListString specList specTerms.getBuckets().stream().map(bucket - bucket.getKeyAsString()).collect(Collectors.toList());resultMap.put(specList, specList(specList));
//16. 返回当前页resultMap.put(pageNum, pageNum);
return resultMap;}
return null;}3测试
使用postman测试分页
二、 搜索排序
1 排序分析
排序这里总共有根据价格排序、根据评价排序、根据新品排序、根据销量排序排序要想实现只需要告知排序的域以及排序方式即可实现。
价格排序只需要根据价格高低排序即可降序价格高-低升序价格低-高
评价排序评价分为好评、中评、差评可以在数据库中设计3个列用来记录好评、中评、差评的量每次排序的时候好评的比例来排序当然还要有条数限制评价条数需要超过N条。
新品排序直接根据商品的发布时间或者更新时间排序。
销量排序销量排序除了销售数量外还应该要有时间段限制。
2 排序代码实现
这里我们不单独针对某个功能实现排序我们只需要在后台接收2个参数分别是排序域名字和排序方式代码如下 Overridepublic Map search(MapString, String searchMap) throws Exception {MapString, Object resultMap new HashMap();
//有条件才查询Esif (null ! searchMap) {//组合条件对象BoolQueryBuilder boolQuery QueryBuilders.boolQuery();//0:关键词if (!StringUtils.isEmpty(searchMap.get(keywords))) {boolQuery.must(QueryBuilders.matchQuery(name, searchMap.get(keywords)).operator(Operator.AND));}//1:条件 品牌if (!StringUtils.isEmpty(searchMap.get(brand))) {boolQuery.filter(QueryBuilders.termQuery(brandName, searchMap.get(brand)));}
//2:条件 规格for (String key : searchMap.keySet()) {if (key.startsWith(spec_)) {String value searchMap.get(key).replace(%2B, );boolQuery.filter(QueryBuilders.termQuery(specMap. key.substring(5) .keyword,value));}}//3:条件 价格if (!StringUtils.isEmpty(searchMap.get(price))) {String[] p searchMap.get(price).split(-);boolQuery.filter(QueryBuilders.rangeQuery(price).gte(p[0]));if (p.length 2) {boolQuery.filter(QueryBuilders.rangeQuery(price).lte(p[1]));}}
//4. 原生搜索实现类NativeSearchQueryBuilder nativeSearchQueryBuilder new NativeSearchQueryBuilder();nativeSearchQueryBuilder.withQuery(boolQuery);
//6. 品牌聚合(分组)查询String skuBrand skuBrand;nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms(skuBrand).field(brandName));
//7. 规格聚合(分组)查询String skuSpec skuSpec;nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms(skuSpec).field(spec.keyword));
//8: 排序if (!StringUtils.isEmpty(searchMap.get(sortField))) {if (ASC.equals(searchMap.get(sortRule))) {nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort(searchMap.get(sortField)).order(SortOrder.ASC));} else {
nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort(searchMap.get(sortField)).order(SortOrder.DESC));}
}
String pageNum searchMap.get(pageNum);if (null pageNum) {pageNum 1;}//9: 分页nativeSearchQueryBuilder.withPageable(PageRequest.of(Integer.parseInt(pageNum) - 1, Page.pageSize));
//10: 执行查询, 返回结果对象AggregatedPageSkuInfo aggregatedPage esTemplate.queryForPage(nativeSearchQueryBuilder.build(), SkuInfo.class, new SearchResultMapper() {Overridepublic T AggregatedPageT mapResults(SearchResponse searchResponse, ClassT aClass, Pageable pageable) {
ListT list new ArrayList();
SearchHits hits searchResponse.getHits();if (null ! hits) {for (SearchHit hit : hits) {SkuInfo skuInfo JSON.parseObject(hit.getSourceAsString(), SkuInfo.class);list.add((T) skuInfo);}}return new AggregatedPageImplT(list, pageable, hits.getTotalHits(), searchResponse.getAggregations());}});
//11. 总条数resultMap.put(total, aggregatedPage.getTotalElements());//12. 总页数resultMap.put(totalPages, aggregatedPage.getTotalPages());//13. 查询结果集合resultMap.put(rows, aggregatedPage.getContent());
//14. 获取品牌聚合结果StringTerms brandTerms (StringTerms) aggregatedPage.getAggregation(skuBrand);ListString brandList brandTerms.getBuckets().stream().map(bucket - bucket.getKeyAsString()).collect(Collectors.toList());resultMap.put(brandList, brandList);
//15. 获取规格聚合结果StringTerms specTerms (StringTerms) aggregatedPage.getAggregation(skuSpec);ListString specList specTerms.getBuckets().stream().map(bucket - bucket.getKeyAsString()).collect(Collectors.toList());resultMap.put(specList, specList(specList));
//16. 返回当前页resultMap.put(pageNum, pageNum);
return resultMap;}
return null;}3测试
使用postman测试 根据价格降序
{keywords:手机,pageNum:1,sortRule:DESC,sortField:price}根据价格升序
{keywords:手机,pageNum:1,sortRule:ASC,sortField:price}