1.2 实现思路 (1)后端使用匹配查询和布尔查询 (2)前端使用thymeleaf模板渲染 (3)前端向后端传递map(因为提交的不仅仅是关键字,还有品牌、规格、分类等信息) (4)后端向前端返回map(因为返回的不仅仅是列表,还有商品分类、品牌和规格列表等数据) 1.3 代码实现1.3.1 集成elasticsearch高级客户端(1)qingcheng_service_goods工程pom.xml新增依赖 <dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.5.3</version>
</dependency>(2)qingcheng_service_goods工程新增工厂类 public class RestClientFactory {
public static RestHighLevelClient getRestHighLevelClient(String hostname,int port){
HttpHost http=new HttpHost(hostname,port,"http");
RestClientBuilder builder= RestClient.builder(http);//rest构建器
return new RestHighLevelClient(builder);//高级客户端对象 (连接)
}
}(3)qingcheng_service_goods工程applicationContext-service.xml新增配置 <!--es client-->
<bean id="restHighLevelClient" class="com.qingcheng.service.impl.RestClientFactory" factory-method="getRestHighLevelClient">
<constructor-arg index="0" value="127.0.0.1"></constructor-arg>
<constructor-arg index="1" value="9200"></constructor-arg>
</bean>1.3.2 关键字搜索逻辑(1)qingcheng_interface工程新增接口 SkuSearchService 服务接口新增方法定义 public interface SkuSearchService {
public Map search(Map<String,String> searchMap);
}(2)qingcheng_service_goods工程新增服务实现类SkuSearchServiceImpl 实现此方法,实现关键字查询 @Service
public class SkuSearchServiceImpl implements SkuSearchService {
@Autowired
private RestHighLevelClient restHighLevelClient;
public Map search(Map<String,String> searchMap) {
//1.封装查询请求
SearchRequest searchRequest=new SearchRequest("sku");
searchRequest.types("doc"); //设置查询的类型
SearchSourceBuilder searchSourceBuilder=new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();//布尔查询构建器
//1.1 关键字搜索
if(searchMap.get("keywords")!=null){
MatchQueryBuilder matchQueryBuilder= QueryBuilders.matchQuery("name",searchMap.get("keywords"));
boolQueryBuilder.must(matchQueryBuilder);
}
searchSourceBuilder.query(boolQueryBuilder);
searchRequest.source(searchSourceBuilder);
//2.封装查询结果
Map resultMap=new HashMap();
try {
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits();
long totalHits = searchHits.getTotalHits();
System.out.println("记录数:"+totalHits);
SearchHit[] hits = searchHits.getHits();
//2.1 商品列表
List<Map<String,Object>> resultList=new ArrayList<Map<String, Object>>();
for(SearchHit hit:hits){
Map<String, Object> skuMap = hit.getSourceAsMap();
resultList.add(skuMap);
}
resultMap.put("rows",resultList);
} catch (IOException e) {
e.printStackTrace();
}
return resultMap;
}
}(3)qingcheng_web_portal工程新增类 @Controller
public class SearchController {
@Reference
private SkuSearchService skuSearchService;
@GetMapping("/search")
public String search(Model model, @RequestParam Map<String, String> searchMap) throws Exception {
//字符集处理
searchMap = WebUtil.convertCharsetToUTF8(searchMap);
//远程调用接口
Map result = skuSearchService.search(searchMap);
model.addAttribute("result", result);
return "search";
}
}WebUtil类是工具类,用于字符集转码,资源中提供 1.3.3 模板构建(1)qingcheng_web_portal工程新增模板,将资源\静态原型\网站前台\search.htm拷贝到WEB-INF下,并进行以下修改 <html xmlns:th="http://www.thymeleaf.org">遍历查询结果 <ul class="yui3-g">
<li class="yui3-u-1-5" th:each="sku:${result.rows}">
<div class="list-wrap">
<div class="p-img">
<a href="item.html" target="_blank"><img th:src="${sku.image}" /></a>
</div>
<div class="price">
<strong>
<em>¥</em>
<i th:text="${#numbers.formatDecimal(sku.price/100.0,0,2)}"></i>
</strong>
</div>
<div class="attr">
<em th:text="${sku.name}"></em>
</div>
<div class="operate">
<a href="success-cart.html" target="_blank" class="sui-btn btn-bordered btn-danger">加入购物车</a>
<a href="javascript:void(0);" class="sui-btn btn-bordered">收藏</a>
</div>
</div>
</li>
</ul>测试 浏览器输入 http://localhost:9102/search.do?keywords=手机 (2)修改index.html的关键字搜索表单 <form action="/search.do" class="sui-form form-inline">
<!--searchAutoComplete-->
<div class="input-append">
<input type="text" name="keywords" id="autocomplete" class="input-error input-xxlarge" />
<button class="sui-btn btn-xlarge btn-danger" type="submit" >搜索</button>
</div>
</form>修改search.html的关键字搜索表单,内容同上 2. 商品分类过滤2.1 需求分析以关键字作为查询条件,查询结果中包含的商品分类,在页面中显示出来 file://D:/%E5%AD%A6%E4%B9%A0%E7%94%A8/%E9%9D%92%E5%9F%8E%E9%A1%B9%E7%9B%AE/%E8%AE%B2%E4%B9%89/%E9%A1%B9%E7%9B%AE2/%E8%AE%B2%E4%B9%89/img/4-3.png?lastModify=1565765131 点击商品分类,按商品分类对结果进行过滤查询,并且在查询条件列表中添加已经选择的商品分类标签,隐藏搜索面板中的商品分类一行。 点击条件标签的“×”,取消该过滤条件 2.2 实现思路(1)商品分类列表的显示使用聚合查询 (2)使用过滤查询 2.3 代码实现 2.3.1 商品分类列表(1)修改SkuSearchServiceImpl的search方法,在第一段代码(封装查询请求)的末尾处添加以下代码: //聚合查询(商品分类)
TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("sku_category").field("categoryName");
searchSourceBuilder.aggregation(termsAggregationBuilder); 在第二段代码中添加以下代码: //2.2 商品分类列表
Aggregations aggregations = searchResponse.getAggregations();
Map<String, Aggregation> aggregationMap = aggregations.getAsMap();
Terms terms = (Terms) aggregationMap.get("sku_category");
List<? extends Terms.Bucket> buckets = terms.getBuckets();
List<String> categoryList=new ArrayList();
for( Terms.Bucket bucket:buckets ){
categoryList.add(bucket.getKeyAsString());
}
resultMap.put("categoryList",categoryList);(2)修改qingcheng_web_portal的search.html 商品分类列表 <div class="type-wrap">
<div class="fl key">商品分类</div>
<div class="fl value" th:each="category:${result.categoryList}">
<span>
<a href="javascript:void(0)" th:utext="${category+' '} " ></a>
</span>
</div>
<div class="fl ext"></div>
</div>2.3.2 分类过滤查询
|