这里是引用
查看下品牌的聚合、10个brand
GET /goods/_search
{
"size": 0
, "aggs": {
"brands": {
"terms": {
"field": "brandId"
}
}
}
}
添加2个字段集合,分类,品牌
/**
* @auther SyntacticSugar
* @data 2018/12/21 0021下午 9:24
*/
public @Data class SearchResult extends PageResult<Goods> {
private List<Category> categoryList;
private List<Brand> brandList ;
//
public SearchResult(Long total, Long totalPage, List<Goods> items, List<Category> categories, List<Brand> brands) {
super(total, totalPage, items);
this.categoryList = categories;
this.brandList = brands;
}
}
搜索中进行聚合、
// 添加 2 个集合,分类,品牌
ArrayList<Category> categories = new ArrayList<>();
ArrayList<Brand> brands = new ArrayList<>();
//聚合
String categoriesAggName="category";
String brandsAggName="brand";
// 聚合不能使用分词
queryBuilder.addAggregation(AggregationBuilders.terms(categoriesAggName).field("cid3"));
queryBuilder.addAggregation(AggregationBuilders.terms(brandsAggName).field("brandId"));
//获取搜索的结果
AggregatedPage<Goods> search = (AggregatedPage<Goods>) this.searchRepository.search(queryBuilder.build());
//获取 terms
LongTerms categoryTerms = (LongTerms) search.getAggregation(categoriesAggName);
LongTerms brandTerms = (LongTerms) search.getAggregation(brandsAggName);
//获取桶
List<LongTerms.Bucket> categoryBuckets = categoryTerms.getBuckets();
List<LongTerms.Bucket> brandBuckets= brandTerms.getBuckets();
// 获取结果
ArrayList<Long> cids = new ArrayList<>();
for (LongTerms.Bucket categoryBucket : categoryBuckets) {
//获取cids 、brandIds
cids.add(categoryBucket.getKeyAsNumber().longValue());
}
ArrayList<Long> brandIds = new ArrayList<>();
for (LongTerms.Bucket brandBucket : brandBuckets) {
brandIds.add(brandBucket.getKeyAsNumber().longValue());
}
// 遍历brandIds、查询获取brand
brandIds.forEach(bid->brands.add(brandClient.queryBrandById(bid)));
、、
然后继续往下码、
添加分类
// 查询cids 、获取category
List<String> categoryNames = categoryClient.queryNameByIds(cids);
for (int i = 0; i < categoryNames.size(); i++) {
Category category1 = new Category();
category1.setName(categoryNames.get(i));
category1.setId(brandIds.get(i));
//添加到categories
categories.add(category1);
}
这时候,分类仅仅是1个,分类下有brands 供选择;
根据 cid3 和brandId 来过滤所选择的商品,
所以添加过滤条件、
添加filters 过滤条件,是一个数组,在请求返回是一个数据的对象,包含k 和options
data: {
ly,
search: {
key: "", // 搜索页面的关键字
page: 1 // 默认第一页,需要判断
},
goodsList: [],
total: 0,
totalPage: 0,
toPage: 1,
filters:[], // 过虑参数有很多
},
请求返回值response:
// 过滤条件返回值
this.filters.push({
// bug 一次,异常显示品牌,分类,以及图片
K:"cid3",
options:data.categoryList,
})
this.filters.push({
K:"brandId",
options:data.brandList,
})
刷新页面,返回值有filters数组,其包含2个对象
bug 出现,原因为K 在分桶返回值中显示的是k 、filter.K错误
更改为k 解决、
这地方做一个动态的加载、
网络制式、屏幕尺寸,摄像头像素,价格需要根据选择加载、
刷新、
判断展示分类,以及品牌
聚合
分桶聚合之后,
前端
//过滤条件添加specs
data.specs.forEach(spec=>{
//name属性,值option
spec.options=spec.options.map(option=>({name:option}))
this.filters.push(spec)
})
[
{
"k":"规格参数名",
"options":["规格参数值","规格参数值"]
}
]
后端
//解析聚合
specParams.forEach(specParam -> {
String name = specParam.getName();
StringTerms stringTerms = (StringTerms) aggregatedPage.getAggregation(name);
Map<String,Object> spec = new HashMap<>();
spec.put("k",name);
//遍历动态分桶的结果,获取其中的值,赋值给map的options属性
List<StringTerms.Bucket> buckets = stringTerms.getBuckets();
List<Object> options = new ArrayList<>();
for (StringTerms.Bucket bucket : buckets) {
options.add(bucket.getKeyAsString());
}
spec.put("options",options);
specs.add(spec);
});
data添加filter,并在created进行判断filter 是否为空,把filter 拼接到url
data: {
ly,
search: {
key: "", // 搜索页面的关键字
page: 1 ,// 默认第一页,需要判断
filter:{} , // 过滤条件
},
goodsList: [],
total: 0,
totalPage: 0,
toPage: 1,
filters: [], // 过虑参数有很多
show:false, // 是否展开过滤条件
},
created() {
// 判断是否有请求参数
if (!location.search) {
return;
}
// 将请求参数转为对象
const search = ly.parse(location.search.substring(1));
search.page = search.page ? parseInt(search.page) : 1;
// 初始化排序
search.sortBy = search.sortBy || "";
search.desc = search.desc === "true" || false;
// filter
search.filter=search.filter||{};
// 记录在data的search对象中
this.search = search;
// 发起请求,根据条件搜索
this.searchFromServer();
},
写方法,判断选择的参数、K:V
search: {
key: "", // 搜索页面的关键字
page: 1 ,// 默认第一页,需要判断
filter:{} , // 过滤条件
},
// filter
selectFilter(key,option){
//定义变量,并对其赋值 Object.assign(T,U)把后面的值赋值给T
const obj={};
Object.assign(obj,this.search);
// 对key 判断
if (key !== 'cid3' && key !== 'brandId') {
// 普通选项
obj.filter[key]=option.name;
this.search=obj;
}else {
// 特殊选项
option=option.id;
obj.filter[key]=option;
this.search=obj;
}
}
把方法添加到每一个选项的标签中、
@click="selectFilter(filter.k,option)"
allowDots: true,
对查询条件进行处理,当选择某一分类的具体参数时候,对这些参数及进行聚合,
1、添加查询条件
2、在specs获取参数时候,传递queryBuilder 参数
/**
* 根据请求查询的条件生成查询条件对象
* 把查询条件添加给查询条件构建对象
*/
QueryBuilder query = buildBasicQueryWithFilter(searchRequest);
queryBuilder.withQuery(query);
if (cids.size()==1){
specs = getSpecs(cids.get(0),query);
// specs = getSpecs(cids.get(0));
}
util
// 构建基本查询条件
private QueryBuilder buildBasicQueryWithFilter(SearchRequestParams request) {
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
// 基本查询条件
queryBuilder.must(QueryBuilders.matchQuery("all", request.getKey()).operator(Operator.AND));
// 过滤条件构建器
BoolQueryBuilder filterQueryBuilder = QueryBuilders.boolQuery();
// 整理过滤条件
Map<String, String> filter = request.getFilter();
for (Map.Entry<String, String> entry : filter.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
// 商品分类和品牌已经聚合
if (key != "cid3" && key != "brandId") {
key = "specs." + key + ".keyword";
}
// 字符串类型,进行term查询
filterQueryBuilder.must(QueryBuilders.termQuery(key, value));
}
// 添加过滤条件
queryBuilder.filter(filterQueryBuilder);
return queryBuilder;
}