携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第29天,点击查看活动详情
每日英语:
Sometimes a little discomfort in the beginning can save much pain down the road.
翻译:有时起初的隐忍可以避免一路的疼痛。 ——《怦然心动》
1. 商品搜索排序实现
1.1 排序搜索分析
排序搜索有多种排序方式,我们可以把排序升序、降序当做一个参数,把排序的域当做一个参数,无论是哪种排序方式,只需要把这两个参数传到后端服务即可。我们定义一下传参数规则:
1、排序域:sfield
2、排序方式:sm
例如:根据价格升序
sfield=price
sm=ASC
例如:新品排序
sfield=updateTime
sm=DESC
1.2 排序实现
在com.xz.mall.search.service.impl.SkuSearchServiceImpl#queryBuilder方法中添加如下代码 即可:
//排序
Object sfield = searchMap.get("sfield");
Object sm = searchMap.get("sm");
if (!ObjectUtils.isEmpty(sfield) && !ObjectUtils.isEmpty(sm)) {
queryBuilder.withSort(
SortBuilders.fieldSort(sfield.toString()) //指定排序域
.order(SortOrder.valueOf(sm.toString())) //排序方式
);
}
2. 商品搜索高亮显示
2.1 高亮原理分析
高亮是指当我们搜索商品的时候,商品列表中如何和你搜索的关键词相同,那么它会高亮展示,也就是变色展示,如下京东搜索,其实就是给关键词增加了样式,所以是红色,ES搜索引擎也是一样,也可以实现关键词高亮展示,原理和京东搜索高亮原理一样。
2.2 高亮实现
高亮搜索实现有2个步骤:
1、配置高亮域以及对应的样式
2、从结果集中取出高亮数据,并将非高亮数据换成高亮数据
2.2.1 设置高亮配置
在com.xz.mall.search.service.impl.SkuSearchServiceImpl#search中添加如下高亮代码:
//1.设置高亮信息 关键词前(后)面的标签,设置高亮域
HighlightBuilder.Field field = new HighlightBuilder
.Field("name") //根据指定的域进行高亮查询
.preTags("<span style="color:red">") //关键词高亮前缀
.postTags("</span>") //关键词高亮后缀
.fragmentSize(100); //碎片长度
//2.添加高亮域
queryBuilder.withHighlightFields(field);
2.2.2 结果映射转换
创建一个结果映射转换对象com.xz.mall.search.util.HighlightResultMapper,其实主要是将非高亮转换成高亮数据,代码如下:
public class HighlightResultMapper extends DefaultResultMapper {
/**
* 映射转换,将非高亮数据替换成高亮数据
* @param response
* @param clazz
* @param pageable
* @param <T>
* @return
*/
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
//1.获取所有非高亮数据
SearchHits hits = response.getHits();
//2.循环非高亮数据集合
for (SearchHit hit : hits) {
//非高亮数据
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
//3.获取高亮数据
for (Map.Entry<String, HighlightField> entry : hit.getHighlightFields().entrySet()) {
//4.将非高亮数据替换成高亮数据
String key = entry.getKey();
//如果当前非高亮对象中有该高亮数据对应的非高亮对象,则进行替换
if (sourceAsMap.containsKey(key)){
//高亮碎片
String hlResult = transTxtToArrayToString(entry.getValue().getFragments());
if (!StringUtils.isEmpty(hlResult)) {
//替换高亮
sourceAsMap.put(key, hlResult);
}
}
}
//更新hit的数据
hit.sourceRef(new ByteBufferReference(ByteBuffer.wrap(JSONObject.toJSONString(sourceAsMap).getBytes())));
}
return super.mapResults(response, clazz, pageable);
}
/**
* Text转成字符串
* @param fragments
* @return
*/
private String transTxtToArrayToString(Text[] fragments) {
if (fragments != null) {
StringBuilder str = new StringBuilder();
for (Text fragment : fragments) {
str.append(fragment.toString());
}
return str.toString();
}
return null;
}
}
在com.xz.mall.search.service.impl.SkuSearchServiceImpl中注入对象ElasticsearchRestTemplate:
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;
替换之前的搜索为用elasticsearchRestTemplate来实现:
/**
* 商品关键词搜索
* @param searchMap
* @return
*/
@Override
public Map<String, Object> search(Map<String, Object> searchMap) {
//QueryBuilder->构建搜索条件
NativeSearchQueryBuilder queryBuilder = queryBuilder(searchMap);
//分组搜索调用
group(queryBuilder, searchMap);
//1.设置高亮信息 关键词前(后)面的标签,设置高亮域
HighlightBuilder.Field field = new HighlightBuilder
.Field("name") //根据指定的域进行高亮查询
.preTags("<span style="color:red">") //关键词高亮前缀
.postTags("</span>") //关键词高亮后缀
.fragmentSize(100); //碎片长度
queryBuilder.withHighlightFields(field);
//2.并将非高亮数据替换成高亮数据
//skuSearchMapper进行搜索
//Page<SkuEs> page = skuSearchMapper.search(queryBuilder.build());
//AggregatedPage<SkuEs> page = (AggregatedPage<SkuEs>) skuSearchMapper.search(queryBuilder.build());
AggregatedPage<SkuEs> page = elasticsearchRestTemplate.queryForPage(queryBuilder.build(), SkuEs.class, new HighlightResultMapper());
//获取结果集:集合列表、记录总数
Map<String, Object> resultMap = new HashMap<>();
//分组数据解析
parseGroup(page.getAggregations(), resultMap);
//动态属性解析
attrParse(resultMap);
List<SkuEs> list = page.getContent();
resultMap.put("list", list);
resultMap.put("totalElements", page.getTotalElements());
return resultMap;
}
用postman测试关键词搜索,效果如下:
总结:
本篇主要介绍了一下商品搜索排序实现和商品搜索高亮显示实现。