package com.lee.search.service;
import com.lee.search.Repository.GoodsRepository;
import com.lee.search.client.BrandClient;
import com.lee.search.client.CategoryClient;
import com.lee.search.client.SpecificationClient;
import com.lee.search.pojo.Goods;
import com.lee.search.pojo.SearchRequest;
import com.lee.search.pojo.SearchResult;
import com.leyou.item.pojo.Brand;
import com.leyou.item.pojo.Category;
import com.leyou.item.pojo.SpecParam;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.LongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.FetchSourceFilter;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 聚合查询:根据页面请求的过滤条件被选项,动态显示 SearchResult 对象的数据(页面过滤可选项数据 和 分页商品搜索结果)
*/
@Service
public class SearchService {
@Autowired
private GoodsRepository goodsRepository;
@Autowired
private CategoryClient categoryClient;
@Autowired
private BrandClient brandClient;
@Autowired
private SpecificationClient specClient;
private Logger logger = LoggerFactory.getLogger(SearchService.class);
public SearchResult search(SearchRequest searchRequest) {
//定义分类和品牌存放的集合
List<Category> categories = null;
List<Brand> brands = null;
List<Map<String, Object>> specs = null;
//1、创建原生查询过滤器
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
//2、指定查询的字段,即指定结果集返回的字段
queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{"id", "skus", "subTitle", "price"}, null));
//3、加入请求中的过滤条件
queryBuilder.withQuery(getFilterQueryBuilder(searchRequest));
//3、加入分页,es的分页从1开始
queryBuilder.withPageable(PageRequest.of(searchRequest.getPage() - 1, searchRequest.getSize()));
//4、加入请求中的排序条件
String sortBy = searchRequest.getSortBy();
Boolean descending = searchRequest.getDescending();
if (StringUtils.isNotBlank(sortBy)) {
queryBuilder.withSort(SortBuilders.fieldSort(sortBy).order(descending ? SortOrder.DESC : SortOrder.ASC));
}
//5、构建聚合,品牌和分类都需要进行聚合,会得到2个聚合结果
String aggCname = "aggCname"; //聚合名称
String aggBname = "aggBname"; //聚合名称
queryBuilder.addAggregation(AggregationBuilders.terms(aggCname).field("cid3")); //field:聚合字段 ,根据最小的3级分类聚合
queryBuilder.addAggregation(AggregationBuilders.terms(aggBname).field("brandId")); //根据品牌id聚合,得到每个品牌在页面的过滤栏的信息
//进行聚合查询
AggregatedPage<Goods> resultPage = (AggregatedPage<Goods>) goodsRepository.search(queryBuilder.build());
//获得分类聚合结果
categories = getCategoryAggResult(aggCname, resultPage);
//获得品牌聚合结果
brands = getBrandAggResult(aggBname, resultPage);
//选中一个商品分类后才显示对应的规格参数过滤项,即仅当分类数为1时进行规格参数的聚合
if (categories != null && categories.size() == 1) {
//获取规格参数聚合结果
specs = getSpecAggResult(categories);
}
return new SearchResult(resultPage.getTotalElements(), (long) resultPage.getTotalPages(), resultPage.getContent(), categories, brands, specs);
}
private QueryBuilder getFilterQueryBuilder(SearchRequest searchRequest) {
try {
//查询字段中包含布尔类型的查询构建器
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
//获取searchRequest中的属性
String key = searchRequest.getKey();
Map<String, String> filter = searchRequest.getFilter();
//判断搜索条件是否为空
if (StringUtils.isBlank(key)) {
return null;
}
//构建搜索条件
// 添加must的条件 此处为匹配Goods中的all字段
queryBuilder.must(QueryBuilders.matchQuery("all", key));
BoolQueryBuilder filterQueryBuilder = QueryBuilders.boolQuery();
if (!filter.isEmpty()) {
for (Map.Entry<String, String> filterEntry : filter.entrySet()) {
String name = filterEntry.getKey();
String value = filterEntry.getValue();
//过滤条件中,分类和品牌传入的都是id,要进行额外的判断
if (name != "cid2" && name != "brandId") {
name = "specs." + name + ".keyword";
}
filterQueryBuilder.must(QueryBuilders.termQuery(name, value)); //分词精确查询
}
}
queryBuilder.filter(filterQueryBuilder);
return queryBuilder;
} catch (Exception e) {
logger.error("构建过滤参数出现异常:{}", e);
e.printStackTrace();
}
return null;
}
private List<Map<String, Object>> getSpecAggResult(List<Category> categories) {
try {
//传入的categories只有1个,查询该分类对应的所有规格参数
List<SpecParam> specParams = this.specClient.querySpecParam(null, categories.get(0).getId(), true, null);
//进行聚合之后将每一个SpecParam对象拼为Map集合以{k:specparam.name,options:同名聚合结果,即一个Aggregation中的所有桶信息}
NativeSearchQueryBuilder query = new NativeSearchQueryBuilder();
//对每一个规格参数都做聚合
specParams.forEach(specParam -> {
String key = specParam.getName();
query.addAggregation(AggregationBuilders.terms(key) //聚合名称
.field("specs." + key + ".keyword")); //聚合的字段
});
AggregatedPage<Goods> search = (AggregatedPage<Goods>) this.goodsRepository.search(query.build());
//解析聚合结果,封装成集合返回
List<Map<String, Object>> specs = new ArrayList<>();
//将所有的聚合转为map形式,方便获取,key为specs中的每一个规格参数名称
Map<String, Aggregation> aggMap = search.getAggregations().asMap();
for (SpecParam specParam : specParams) {
Map<String, Object> specMap = new HashMap<>();
String key = specParam.getName();
//根据key获取聚合Map中对应的每一个聚合,即每一个Aggregation对象
StringTerms aggregation = (StringTerms) aggMap.get(key);
//将每一个聚合对象中的桶中的数据取出,封装为一个list集合,即为每一个规格参数所对应的�
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
使用整套SpringCloud组件,使用JWT结合非对称密钥实现分布式授权中心,使用F (1343个子文件)
.babelrc 317B
Order.class 14KB
GoodsServiceImpl.class 13KB
OrderService.class 8KB
GoodsController.class 8KB
Sku.class 7KB
CartService.class 7KB
OrderController.class 7KB
PayHelper.class 6KB
BrandServiceImpl.class 6KB
GoodsPageService.class 6KB
CookieUtils.class 6KB
UserService.class 5KB
AddressDTO.class 5KB
OrderStatus.class 5KB
AuthController.class 5KB
BrandController.class 5KB
SpecController.class 5KB
Cart.class 5KB
SpecServiceImpl.class 5KB
User.class 4KB
FileService.class 4KB
JsonUtils.class 4KB
IdWorker.class 4KB
JwtUtils.class 4KB
AuthFilter.class 4KB
Category.class 4KB
UserController.class 3KB
CartController.class 3KB
JwtProperties.class 3KB
PayProperties.class 3KB
PageResult.class 3KB
RsaUtils.class 3KB
SpecGroup.class 3KB
SmsUtils.class 3KB
UploadServiceImpl.class 3KB
SpuBo.class 3KB
OrderDTO.class 3KB
Spu.class 3KB
Md5Utils.class 3KB
NumberUtils.class 3KB
ExceptionResult.class 3KB
CategoryController.class 3KB
JwtTest.class 3KB
JwtTest.class 3KB
LoginInterceptor.class 3KB
LoginInterceptor.class 3KB
SpecParam.class 3KB
JwtProperties.class 3KB
MQListener.class 2KB
CategoryServiceImpl.class 2KB
UploadProperties.class 2KB
OrderDetail.class 2KB
ExceptionEnum.class 2KB
SwaggerConfig.class 2KB
FdfsTest.class 2KB
CartDTO.class 2KB
UserInfo.class 2KB
AuthService.class 2KB
GoodsPageController.class 2KB
JwtProperties.class 2KB
Brand.class 2KB
JwtProperties.class 2KB
GlobalCorsConfig.class 2KB
GoodsApi.class 2KB
UploadController.class 2KB
SpuDetail.class 2KB
MvcConfig.class 2KB
MvcConfig.class 2KB
CommonExceptionHandler.class 2KB
GoodsService.class 2KB
NotifyController.class 2KB
SmsTest.class 2KB
MqListener.class 1KB
CodecUtils.class 1KB
SmsProperties.class 1KB
Stock.class 1KB
PayConfig.class 1KB
ObjectUtils.class 1KB
BrandMapper.class 1KB
PayState.class 1KB
BrandService.class 1KB
SpecificationApi.class 1KB
AllowProperties.class 996B
LyUploadService.class 993B
SpecService.class 967B
IdWorkerConfig.class 955B
LyItemApplication.class 911B
IdWorkerProperties.class 901B
UserApplication.class 900B
GoodsPageApplication.class 895B
CartApplication.class 880B
CategoryMapper.class 865B
LyAuthApplication.class 861B
LyOrderService.class 852B
LyRegistryApplication.class 837B
LyGateWayApplication.class 833B
ThreadUtils.class 823B
ThreadUtils.class 809B
SMSApplication.class 741B
共 1343 条
- 1
- 2
- 3
- 4
- 5
- 6
- 14
资源评论
普通网友
- 粉丝: 1127
- 资源: 5294
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 绿色建筑基本情况表.docx
- 矛盾纠纷大排查大化解切实专项行动分类台账.docx
- 民办培训机构设立核准表.doc
- 母婴保健技术服务人员考核审批表.doc
- 母婴保健技术服务执业许可申请表.doc
- 年度考核登记表.doc
- 年度项目绩效自评表(劳务派遣人员经费).docx
- 企业就业高校毕业生实行养老保险过渡费率试点申报表.docx
- 全市重点工作攻坚行动工作台账(1-12月份).docx
- 送达地址确认书(执行).doc
- EtherCAT总线通信学习资料,一手资料 提供基于stm32 mcuAX58100 ESC实现从站的具体方案,有完整的工程文件,提供源码以及工程配置、程序修改的视频,工程在开发板上已测 提供不同
- 基于springboot+vue框架的企业人事管理系统源码(java毕业设计完整源码).zip
- 机械设计芯片读取及激光打码机(sw18可编辑+2D+BOM+电气图+程序)全套设计资料100%好用.zip
- 基于SpringBoot+Vue的志愿者招募管理系统源码(java毕业设计完整源码).zip
- 基于算例IEEE33还有PG69,使用CPLEX+YALMIP进行二阶锥松弛建模的多时间断面潮流,有配电网重构,最优潮流,以及复现文章,模型,注释清晰,保证可运行
- 基于SpringBoot+Vue的校园篮球联赛管理系统源码(java毕业设计完整源码).zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功