今日目标:
(1)实现品优购价格区间筛选功能
(2)实现搜索结果分页功能
(3)理解多关键字搜索
(4)实现搜索结果排序功能
(5)实现隐藏品牌列表功能
(6)实现搜索页与首页对接功能
(7)完成更新索引库的功能
目录
1、按价格区间筛选
1.1 需求分析
点击搜索面板上的价格区间,实现按价格筛选
1.2 前端
(1)修改goodsController.js中的添加和移除选项方法
(2)页面绑定变量和单击事件
注意:需要初始化price
(3)绑定面包屑变量
1.3 后端
(1)服务层实现(search-service),修改setFilterOptions方法,在方法末尾加入代码
// 设置价格区间
if (!searchMap.get("price").equals("")) {
// 处理条件
String[] price = ((String) searchMap.get("price")).split("-");
if (!price[0].equals("0")) {// 价格不等于0
// 设置价格下限
FilterQuery filterQuery = new SimpleFilterQuery();
Criteria criteria = new Criteria("item_price").greaterThanEqual(price[0]);
filterQuery.addCriteria(criteria);
// 设置到查询对象中
query.addFilterQuery(filterQuery);
}
if (!price[1].equals("*")) {// 有上限
// 设置价格上限
FilterQuery filterQuery = new SimpleFilterQuery();
Criteria criteria = new Criteria("item_price").lessThanEqual(price[1]);
filterQuery.addCriteria(criteria);
// 设置到查询对象中
query.addFilterQuery(filterQuery);
}
}
(2)效果
2、搜索结果分页展示
2.1 需求分析
在搜索功能基础上实现分页查询
2.2 后端
(1)服务层实现(search-service),新增方法
/**
* 设置分页选项,并将分页设置给查询对象
*
* @param searchMap 条件
* @param query 查询对象
*/
private void setPageOptions(Map searchMap, HighlightQuery query) {
// 获取当前页码
Integer pageNo = (Integer) searchMap.get("pageNo");
if (pageNo == null || pageNo < 1) {
// 默认当前页码为1
pageNo = 1;
}
// 获取每页显示记录数
Integer pageSize = (Integer) searchMap.get("pageSize");
if (pageSize == null || pageSize < 1) {
// 默认每页记录数为20
pageSize = 20;
}
// 设置起始记录
query.setOffset((pageNo - 1) * pageSize);
// 设置每页记录数
query.setRows(pageSize);
}
(2)在searchList方法中调用设置分页的方法,并在返回值中添加总页数和总记录数
2.3 前端
(1)构建分页标签,在searchController.js中新增方法,并在search方法中调用
// 分页属性
$scope.pageLabel = [];
buildPageLabel = function () {
// 总页数
var maxPageNo = $scope.resultMap.totalPages;
// 起始页
var firstPage = 1;
// 最后一页
var lastPage = maxPageNo;
if (maxPageNo > 5) {// 如果总页数大于5
// 判断特殊情况
if ($scope.searchMap.pageNo - 3 <= 0) {// 页码下限越界
lastPage = 5;
} else if ($scope.resultMap.pageNo + 2 >= lastPage) {// 页码上限越界
firstPage = maxPageNo - 4;
} else {// 正常情况
firstPage = $scope.resultMap.pageNo - 2;
lastPage = $scope.resultMap.pageNo + 2;
}
}
// 遍历总页数生成分页属性
for (var i = firstPage; i <= lastPage; i++) {
$scope.pageLabel.push(i);
}
}
(2)页面绑定变量,展示分页标签
(3)点击页码或者上下一页,发送请求,在searchController.js中添加方法
// 分页查询
$scope.searchByPage = function(pageNo){
if (pageNo < 1 || pageNo > $scope.resultMap.totalPages) {
return ;
}
// 设置当前页码信息到查询条件中
$scope.searchMap.pageNo = pageNo;
// 执行查询
$scope.search();
}
(4)页面绑定单击事件
(5)输入页面点击确定,查询输入的页码,绑定变量和单击事件
注意:表单输入框输入的值为字符串,我们需要在searchController.js中的searchByPage将pageNo转换成数字
(6)上一页和下一页的不可用样式,在searchController.js中新增方法
// 判断当前页是否是第一页
$scope.isTopPage = function () {
if ($scope.searchMap.pageNo == 1) {
return true;
} else {
return false;
}
}
// 判断当前页是否是最后一页
$scope.isEndPage = function () {
if ($scope.resultMap.totalPages == $scope.searchMap.pageNo) {
return true;
} else {
return false;
}
}
(7)在页面使用三元运算符进行校验
(8)省略号的显示
(9)每次点击查询时,重置当前页码
2.4 搜索优化
当搜索条件中出现空格时,会很大的减少甚至搜索不到结果,所以我们需要在后端将空格处理掉
(1)修改服务层实现,在查询之前,把空格处理掉
3、排序
3.1 需求分析
实现价格的排序(升降序可切换)
3.2 服务层实现(search-service)
(1)在ItemSearchServiceImpl新增方法
/**
* 设置排序
*
* @param searchMap 条件
* @param query 查询对象
*/
private void setSort(Map searchMap, Query query) {
// 获取查询域以及排序方式
String sortValue = (String) searchMap.get("sort");
String sortField = (String) searchMap.get("sortField");
// 设置排序
if (sortValue != null && !sortValue.equals("")) {
if(sortValue.equals("ASC")) {// 升序
Sort sort = new Sort(Sort.Direction.ASC, "item_" + sortField);
query.addSort(sort);
}
if(sortValue.equals("DESC")) {// 升序
Sort sort = new Sort(Sort.Direction.DESC, "item_" + sortField);
query.addSort(sort);
}
}
}
(2)在searchList方法中调用
3.3 按价格排序 -- 前端
(1)在searchController.js中新增方法
// 排序搜索
$scope.sortSearch = function (sortField, sort) {
// 设置排序字段和排序方式到查询对象中
$scope.searchMap.sort = sort;
$scope.searchMap.sortField = sortField;
// 执行查询
$scope.search();
}
注意:在searchMap中初始化sort和sortField
(2)页面绑定单击事件
3.4 按新品排序 -- 前端
说明:新品就是按上架时间来降序排序
准备工作:因为我们最开始导入solr时,并没有这个业务域,所以我们需要添加业务域(type为date),并在实体类的updateTime上添加Field注解。然后重新将数据导入solr索引库
(1)查看数据是否正确导入索引库
(2)页面绑定单击事件
3.5 按销量排序(实现思路)
(1)增加域item_salecount 用于存储每个SKU的销量数据
(2)编写定时器程序,用于更新每个SKU的销量数据(查询近1个月的销量数据,不是累计数据)
(3)定时器每天只需执行一次,可以设定为凌晨开始执行。
3.6 按评价排序(实现思路)
与按销量排序思路基本相同,有一个细节需要注意:
评论分为好评、中评、差评,我们不能简单地将评论数相加,而是应该根据每种评论加权进行统计。比如好评的权重是3 ,中评的权重是1,而差评的权重是 -3,这样得出的是评价的综合得分。
4、隐藏品牌列表
4.1 需求分析
如果用户输入的是品牌的关键字,则隐藏品牌列表
4.2 前端
(1)在searchController.js中新增方法
// 判断关键字是否包含品牌信息
$scope.keywordsIsBrand = function () {
// 遍历查询结果中的品牌列表
for (var i = 0; i < $scope.resultMap.brandList.length; i++) {
// 判断keywords中是否包含品牌信息
if ($scope.searchMap.keywords.indexOf($scope.resultMap.brandList[i].text) > 0) {// 包含
return true;
}
}
return false;
}
(2)页面绑定判断指令
5、搜索页与首页对接
用户在首页搜索框输入关键字,点击搜索后自动跳转到搜索页展示搜索结果
5.1 首页工程的相关改动
(1)在portal-web工程中的contentController.js中新增方法
// 搜索
$scope.search = function () {
location.href = "http://localhost:9104/search.html#?keywords=" + $scope.keywords;
}
(2)页面绑定变量和单击事件
5.2 搜索工程的相关改动
(1)在searchControllre.js中注入location服务,并在里面新增方法
// 接受首页传送过来的关键字
$scope.loadKeywords = function () {
// 将首页传送的关键字赋值给查询对象
$scope.searchMap.keywords = $location.search()['keywords'];
// 执行查询
$scope.search();
}
(2)使用初始化调用指令调用该方法
(3)效果:在首页输入手机,点击搜索
6、同步更新索引库
6.1 需求分析
在进行商品审核后更新到solr索引库,在商品删除后删除solr索引库中相应的记录.
6.2 商家商品服务模块
(1)sellergoods-interface,在GoodsService类中新增方法
/**
* 按商品id数组和状态查询商品SKU列表
*
* @param ids 商品id数组
* @param status 状态
* @return java.util.List<com.pinyougou.pojo.TbItem>
*/
List<TbItem> findItemListByGoodsIdsAndStatus(Long[] ids, String status);
(2)sellergoods-service,在GoodsServiceImpl类中实现
@Override
public List<TbItem> findItemListByGoodsIdsAndStatus(Long[] ids, String status) {
// 创建查询条件
TbItemExample example = new TbItemExample();
// 封装查询条件
example.createCriteria().andGoodsIdIn(Arrays.asList(ids)).andStatusEqualTo(status);
return itemMapper.selectByExample(example);
}
6.3 商品搜索服务模块
(1)search-interface,在ItemSearchService类中新增方法
/**
* 将商品SKU数据导入索引库
*
* @param itemList 商品SKU列表
*/
void importList(List<TbItem> itemList);
(2)search-service,在ItemSearchServiceImpl类中实现
@Override
public void importList(List<TbItem> itemList) {
// 将itemList放入索引库
solrTemplate.saveBeans(itemList);
solrTemplate.commit();
}
6.4 控制层(manager-web)
(1)修改GoodsController类中的updateStatus方法,注意引入ItemSearchService的服务
7、同步删除索引库
7.1 商品搜索服务模块
(1)search-interface,在ItemSearchService中新增方法
/**
* 按商品id集合删除索引库数据
*
* @param ids 商品id集合
*/
void deleteByGoodsIds(List ids);
(2)search-service,在ItemSearchServiceImpl中实现
@Override
public void deleteByGoodsIds(List ids) {
// 创建查询对象
Query query = new SimpleQuery("*:*");
Criteria criteria = new Criteria("item_goodsid").in(ids);
query.addCriteria(criteria);
// 执行
solrTemplate.delete(query);
solrTemplate.commit();
}
7.2 控制层(manager-web)
(1)在delete方法中,加入逻辑,注意引入ItemSearchService的服务