JAVA全系列 教程
3762个小节阅读:7093.3k
目录
C语言快速入门
JAVA全系列 教程
面向对象的程序设计语言
Python全系列 教程
Python3.x版本,未来主流的版本
人工智能 教程
顺势而为,AI创新未来
大厂算法 教程
算法,程序员自我提升必经之路
C++ 教程
一门通用计算机编程语言
微服务 教程
目前业界流行的框架组合
web前端全系列 教程
通向WEB技术世界的钥匙
大数据全系列 教程
站在云端操控万千数据
AIGC全能工具班
A A
White Night
搜索功能的编写比较复杂,首先搜索条件繁多,有关键字、价格、品牌、规格等。其次返回的结果除了搜索到的商品,还要返回搜索面板,包含关键字对应的品牌、品类、规格等,还要将搜索条件回显回去,供前端操作。接下来我们编写商品的搜索功能。
重写搜索产品功能
xxxxxxxxxx
// 搜索产品
@Override
public GoodsSearchResult search(GoodsSearchParam goodsSearchParam) {
// 1.构造ES搜索条件
// 2.搜索
// 3.将查询结果封装为Page对象
// 4.封装结果对象
// 4.1 查询结果
// 4.2 查询查询参数
// 4.3 查询面板
return null;
}
编写构造ES搜索条件功能
xxxxxxxxxx
/**
* 构造搜索条件
*
* @param goodsSearchParam 查询条件对象
* @return 搜索条件对象
*/
public NativeQuery buildQuery(GoodsSearchParam goodsSearchParam) {
// 1.创建复杂查询条件对象
NativeQueryBuilder nativeQueryBuilder = new NativeQueryBuilder();
BoolQuery.Builder builder = new BoolQuery.Builder();
// 2.如果查询条件有关键词,关键词可以匹配商品名、副标题、品牌字段;否则查询所有商品
if (!StringUtils.hasText(goodsSearchParam.getKeyword())) {
MatchAllQuery matchAllQuery = new MatchAllQuery.Builder().build();
builder.must(matchAllQuery._toQuery());
} else {
String keyword = goodsSearchParam.getKeyword();
MultiMatchQuery keywordQuery = MultiMatchQuery.of(q -> q.query(keyword).fields("goodsName", "caption", "brand"));
builder.must(keywordQuery._toQuery());
}
// 3.如果查询条件有品牌,则精准匹配品牌
String brand = goodsSearchParam.getBrand();
if (StringUtils.hasText(brand)) {
TermQuery brandQuery = TermQuery.of(q -> q.field("brand").value(brand));
builder.must(brandQuery._toQuery());
}
// 4.如果查询条件有价格,则匹配价格
Double highPrice = goodsSearchParam.getHighPrice();
Double lowPrice = goodsSearchParam.getLowPrice();
if (highPrice != null && highPrice != 0) {
RangeQuery lte = RangeQuery.of(q -> q.field("price").lte(JsonData.of(highPrice)));
builder.must(lte._toQuery());
}
if (lowPrice != null && lowPrice != 0) {
RangeQuery gte = RangeQuery.of(q -> q.field("price").gte(JsonData.of(lowPrice)));
builder.must(gte._toQuery());
}
// 5.如果查询条件有规格项,则精准匹配规格项
Map<String, String> specificationOptions = goodsSearchParam.getSpecificationOption();
if (specificationOptions != null && specificationOptions.size() > 0) {
Set<Map.Entry<String, String>> entries = specificationOptions.entrySet();
for (Map.Entry<String, String> entry : entries) {
String key = entry.getKey();
String value = entry.getValue();
if (StringUtils.hasText(key)) {
TermQuery termQuery = TermQuery.of(q -> q.field("specification." + key + ".keyword").value(value));
builder.must(termQuery._toQuery());
}
}
}
nativeQueryBuilder.withQuery(builder.build()._toQuery());
// 6.添加分页条件
PageRequest pageable = PageRequest.of(goodsSearchParam.getPage() - 1, goodsSearchParam.getSize());
nativeQueryBuilder.withPageable(pageable);
// 7.如果查询条件有排序,则添加排序条件
String sortFiled = goodsSearchParam.getSortFiled();
String sort = goodsSearchParam.getSort();
if (StringUtils.hasText(sort) && StringUtils.hasText(sortFiled)) {
Sort sortParam = null;
// 新品的正序是id的倒序
if (sortFiled.equals("NEW")) {
if (sort.equals("ASC")) {
sortParam = Sort.by(Sort.Direction.DESC, "id");
}
if (sort.equals("DESC")) {
sortParam = Sort.by(Sort.Direction.ASC, "id");
}
}
if (sortFiled.equals("PRICE")) {
if (sort.equals("ASC")) {
sortParam = Sort.by(Sort.Direction.ASC, "price");
}
if (sort.equals("DESC")) {
sortParam = Sort.by(Sort.Direction.DESC, "price");
}
}
nativeQueryBuilder.withSort(sortParam);
}
// 8.返回查询条件对象
return nativeQueryBuilder.build();
}
重写搜索产品功能
xxxxxxxxxx
@Override
public GoodsSearchResult search(GoodsSearchParam goodsSearchParam) {
// 1.构造ES搜索条件
NativeQuery query = buildQuery(goodsSearchParam);
// 2.搜索
SearchHits<GoodsES> search = template.search(query, GoodsES.class);
// 3.将查询结果封装为Page对象
// 3.1 将SearchHits转为List
List<GoodsES> content = new ArrayList();
for (SearchHit<GoodsES> goodsESSearchHit : search) {
GoodsES goodsES = goodsESSearchHit.getContent();
content.add(goodsES);
}
// 3.2 将List转为MP的Page对象
Page<GoodsES> page = new Page();
page.setCurrent(goodsSearchParam.getPage()) // 当前页
.setSize(goodsSearchParam.getSize()) // 每页条数
.setTotal(search.getTotalHits()) // 总条数
.setRecords(content); // 结果集
// 4.封装结果对象
// 4.1 查询结果
GoodsSearchResult result = new GoodsSearchResult();
result.setGoodsPage(page);
// 4.2 查询参数
result.setGoodsSearchParam(goodsSearchParam);
// 4.3 查询面板
buildSearchPanel(goodsSearchParam,result);
return result;
}
编写封装查询面板功能,查询面板中包含品牌、分类、规格项。根据查询条件,查询出20条最符合的数据,遍历这些数据,找到它们的品牌、分类、规格项,最后封装到查询结果中。写法如下:
xxxxxxxxxx
/**
* 封装查询面板,封装查询面板,即根据查询条件,找到查询结果关联度前20名的商品进行封装
* @param goodsSearchParam
* @param goodsSearchResult
*/
public void buildSearchPanel(GoodsSearchParam goodsSearchParam,GoodsSearchResult goodsSearchResult){
// 1.构造搜索条件
goodsSearchParam.setPage(1);
goodsSearchParam.setSize(20);
goodsSearchParam.setSort(null);
goodsSearchParam.setSortFiled(null);
NativeQuery query = buildQuery(goodsSearchParam);
// 2.搜索
SearchHits<GoodsES> search = template.search(query, GoodsES.class);
// 3.将结果封装为List对象
List<GoodsES> content = new ArrayList();
for (SearchHit<GoodsES> goodsESSearchHit : search) {
GoodsES goodsES = goodsESSearchHit.getContent();
content.add(goodsES);
}
// 4.遍历集合,封装查询面板
// 商品相关的品牌列表
Set<String> brands = new HashSet();
// 商品相关的类型列表
Set<String> productTypes = new HashSet();
// 商品相关的规格列表
Map<String, Set<String>> specifications = new HashMap();
for (GoodsES goodsES : content) {
// 获取品牌
brands.add(goodsES.getBrand());
// 获取类型
List<String> productType = goodsES.getProductType();
productTypes.addAll(productType);
// 获取规格
Map<String, List<String>> specification = goodsES.getSpecification();
Set<Map.Entry<String, List<String>>> entries = specification.entrySet();
for (Map.Entry<String, List<String>> entry : entries) {
// 规格名
String key = entry.getKey();
// 规格值
List<String> value = entry.getValue();
// 如果没有遍历出该规格,新增键值对,如果已经遍历出该规格,则向规格中添加规格项
if (!specifications.containsKey(key)){
specifications.put(key,new HashSet(value));
}else{
specifications.get(key).addAll(value);
}
}
}
goodsSearchResult.setBrands(brands);
goodsSearchResult.setProductType(productTypes);
goodsSearchResult.setSpecifications(specifications);
}
编写搜索控制器
xxxxxxxxxx
/**
* 搜索商品
* @param goodsSearchParam 搜索条件
* @return 搜索结果
*/
@PostMapping("/search")
public BaseResult<GoodsSearchResult> search(@RequestBody GoodsSearchParam goodsSearchParam){
GoodsSearchResult result = searchService.search(goodsSearchParam);
return BaseResult.ok(result);
}
测试接口