**海量搜索解决方案_Spring Data Solr [篇3/共3篇]*

版权声明:文章为作者自己原创文章,转载请注明出处。 https://blog.csdn.net/qq_37128049/article/details/84782621

今日内容

1. 价格区间过滤搜索
2. 搜索结果分页
3. 多关键字搜索
4. 排序功能  -->价格排序,上架时间排序,销量排序,评价排序...
5. 隐藏品牌类表
6. 搜索页与首页对接
7. 更新索引库

价格区间过滤-- 前端

1. webapp/controller:     	具体路径:webapp/js/controller/searchController.js:
	1. 代码:
		app.controller('searchController',function($scope,searchService){
			//定义搜索对象的结构,category商品搜索类
			//为什么price不用{},因为传price的值只有一个,所以与品牌分类等都一样;
			$scope.searchMap={'keywords':'','category':'','brand':'','spec':{},'price':''};
			//搜索
			$scope.search=function(){
				searchService.search($scope.searchMap).success(
					function(response){
						$scope.resultMap=response;				
					}
				);
		
			};
		
			//添加搜索项,改变searchMap的值
			$scope.addSearchItem=function(key,value){
				if(key=='category'||key=='brand'||key=='price'){
					//如果用户点击的是分类或品牌
					$scope.searchMap[key]=value;
				}else{
					//用户点击的规格选项列表
					$scope.searchMap.spec[key]=value;
				}
		        $scope.search();		//查询
			};
		
			//撤销搜索项
		    $scope.removeSearchItem=function(key){
				if(key=='category'||key=='brand'||key=='price'){
					//如果用户撤销的是分类或品牌
					$scope.searchMap[key]="";
				}else{
					delete $scope.searchMap.spec[key];
				}
		        $scope.search();		//查询
			}
			
		});

	2. 分析:
		* 将price数据添加进searchMap数组并进行判断;
		* 为什么price不用{},因为传price的传入后端的值只有一个,所以与品牌分类等一起进行判断;


2. webapp/search.html:  	具体路径webapp/search.html:
	1. 功能一:点击事件添加搜索值:
		1. 部分改变代码:
				<div class="type-wrap">
						<div class="fl key">价格</div>
						<div class="fl value">
							<ul class="type-list">
								<li>
									<a href="#" ng-click="addSearchItem('price','0-500')">0-500元</a>
								</li>
								<li>
									<a href="#" ng-click="addSearchItem('price','500-1000')">500-1000元</a>
								</li>
								<li>
									<a href="#" ng-click="addSearchItem('price','1000-1500')">1000-1500元</a>
								</li>
								<li>
									<a href="#" ng-click="addSearchItem('price','1500-2000')">1500-2000元</a>
								</li>
								<li>
									<a href="#" ng-click="addSearchItem('price','2000-3000')">2000-3000元 </a>
								</li>
								<li>
									<a href="#" ng-click="addSearchItem('price','3000-*')">3000元以上</a>
								</li>
							</ul>
						</div>
		
	
		2. 分析: 将前端的数据通过点击事件传入,再通过controller.js进行判断添加搜索值;
		
	2. 功能二:移除添加的搜索值
		1. 部分改变代码:
					<ul class="tags-choose">
						<li class="tag" ng-if="searchMap.category!=''" ng-click="removeSearchItem('category')">商品分类:{{searchMap.category}}<i class="sui-icon icon-tb-close"></i></li>
						<li class="tag" ng-if="searchMap.brand!=''" ng-click="removeSearchItem('brand')">品牌:{{searchMap.brand}}<i class="sui-icon icon-tb-close"></i></li>
						<li class="tag" ng-repeat="(key,value) in searchMap.spec" ng-click="removeSearchItem(key)">{{key}}:{{value}}<i class="sui-icon icon-tb-close"></i></li>
						<li class="tag" ng-if="searchMap.price!=''" ng-click="removeSearchItem('price')">品牌:{{searchMap.price}}<i class="sui-icon icon-tb-close"></i></li>
					</ul>
		2. 分析: 添加一列关于price的代码,它的作用是将选择的搜索条件值进行移除;

	3. 功能三:添加到搜索值列表时让price列表消失:
	
		1. 部分改变代码:
					<div class="type-wrap" ng-if="searchMap.price==''">
					<div class="fl key">价格</div>
					<div class="fl value">
						<ul class="type-list">
							<li>
								<a href="#" ng-click="addSearchItem('price','0-500')">0-500元</a>
							</li>
							<li>
								<a href="#" ng-click="addSearchItem('price','500-1000')">500-1000元</a>
							</li>
							<li>
								<a href="#" ng-click="addSearchItem('price','1000-1500')">1000-1500元</a>
							</li>
							<li>
								<a href="#" ng-click="addSearchItem('price','1500-2000')">1500-2000元</a>
							</li>
							<li>
								<a href="#" ng-click="addSearchItem('price','2000-3000')">2000-3000元 </a>
							</li>
							<li>
								<a href="#" ng-click="addSearchItem('price','3000-*')">3000元以上</a>
							</li>
						</ul>
					</div>
					<div class="fl ext">
					</div>
				</div>
		2. <div class="type-wrap" ng-if="searchMap.price==''">,这里通过判断如果searchMap.price的值如果为空的话,才显示价格范围列表;如果已经添加了价格搜索条件,那么这列就不再显示;

价格区间过滤-- 后端

1. 部分代码:
	    //1.5 按价格过滤
        if(!"".equals(searchMap.get("price"))){
            String[] price=((String)searchMap.get("price")).split("-");
            if (!price[0].equals("0")){    //如果最低价格不等于0
                FilterQuery filterQuery=new SimpleFilterQuery();
                Criteria filterCriteria=new Criteria("item_price").greaterThanEqual(price[0]);
                filterQuery.addCriteria(filterCriteria);
                query.addFilterQuery(filterQuery);
            }
            if (!price[1].equals("*")){//如果最高价格不等于 *
                FilterQuery filterQuery=new SimpleFilterQuery();
                Criteria filterCriteria=new Criteria("item_price").greaterThanEqual(price[1]);
                filterQuery.addCriteria(filterCriteria);
                query.addFilterQuery(filterQuery);
            }
        }	

2. 分析:
	* 这里通过将接收到的price值进行split切分成两个值;然后进行判断最低价格和最高价格,将两个值放入一个安全的区间,并进行价格过滤,使用greaterThanEqual【大于】和lessThanEqual【小于】进行范围查询集合列表,然后存入filterQuery,再将其存入query进行查询;

分页-- 后端

1. 前端传入哪些数据?		
	* 当前页码	pageNo
	* 每页多少条数据		pageSize


2. 代码演示:
	1. 部分代码:
			       //1.6 分页查询
		        Integer pageNo=(Integer)searchMap.get("pageNo");            //获取页码
		        //如果为空则给page赋值
		        if (pageNo==null){
		            pageNo=1;
		        }
		        Integer pageSize=(Integer)searchMap.get("pageSize");        //获取页大小
		        if (pageSize==null){
		            pageSize=20;
		        }
		
		        //起始索引
		        query.setOffset((pageNo-1)* pageSize);              //这是一个固定公式,求起始索引的时候均可使用此方法
		        query.setRows(pageSize);                //每页记录数
		
		
		
		
		
		        //************  获取高亮结果集 **************
		        //高亮页显示对象
		        HighlightPage<TbItem> page=solrTemplate.queryForHighlightPage(query, TbItem.class);
		
		        //高亮入口集合(每条记录的高亮入口)
		        List<HighlightEntry<TbItem>> entryList=page.getHighlighted();
		        for (HighlightEntry<TbItem> entry : entryList) {
		            //获取高亮列表(高亮域的个数)
		            List<HighlightEntry.Highlight> highlightList=entry.getHighlights();
		           /* for (HighlightEntry.Highlight h : highlightList) {
		                List<String> sns=h.getSnipplets();
		                System.out.println(sns);
		            }*/
		            if (highlightList.size() > 0 && highlightList.get(0).getSnipplets().size() > 0) {
		                TbItem item=entry.getEntity();
		                item.setTitle(highlightList.get(0).getSnipplets().get(0));
		            }
		        }
		        map.put("rows", page.getContent());
		        //上面已经将一些分页必须的数据存入了rows集合中;然后下面的总页数和总记录数是对分页的一些扩展;   必备:起始索引,结束索引,具体数据...
		        map.put("totalPages",page.getTotalPages());      //总页数
		        map.put("total",page.getTotalElements());           //总记录数
		        return map;
		    }
		
	2. 分析:这里通过获取前端给的页码和页大小可以得到起始索引和结束索引,数据库进行这两个条件进行查询结果并封装到rows集合中;除了这些数据,还需要总页数和总记录数,就可以完善前端分页所需要的数据了;	

分页-- 前端-- 构建分页栏

1. webapp/js/controller/searchController.js:
	1. 修改1  [向集合中添加分页初始化数据]:
		1. 部分代码
			$scope.searchMap={'keywords':'','category':'','brand':'','spec':{},'price':'','pageNo':1,'pageSize':40};
		2. 分析:
			* 这里存入pageNo和Size的默认值;虽然后端已经有了对pageNo和pageSize初始值的赋值,但是写上可以增强程序的阅读性和健壮性;
	

	2. 修改2		[构建分页状态栏。]:
		1. 部分代码:
					//搜索
				$scope.search=function(){
					searchService.search($scope.searchMap).success(
						function(response){
							$scope.resultMap=response;
			                buildPageLabel();		//构建分页状态栏
						}
					);
			
				};
			
				buildPageLabel=function(){
			        //构建分页状态栏
			        $scope.pageLabel=[];
			        for(var i=1;i<=$scope.resultMap.totalPages;i++){
			            $scope.pageLabel.push(i);
			        }
			
			    };
		2. 分析:
			* 这里构建的分页状态栏,是新建pageLabel数组,将后端传入的totalPages赋值给该数组;
			* 为了避免代码臃肿,将代码提取到方法中;

2. webapp/search.html:

	1.修改1:
		1. 部分代码:
			<ul class="tags-choose">
				<li class="tag" ng-if="searchMap.category!=''" ng-click="removeSearchItem('category')">商品分类:{{searchMap.category}}<i class="sui-icon icon-tb-close"></i></li>
				<li class="tag" ng-if="searchMap.brand!=''" ng-click="removeSearchItem('brand')">品牌:{{searchMap.brand}}<i class="sui-icon icon-tb-close"></i></li>
				<li class="tag" ng-repeat="(key,value) in searchMap.spec" ng-click="removeSearchItem(key)">{{key}}:{{value}}<i class="sui-icon icon-tb-close"></i></li>
				<li class="tag" ng-if="searchMap.price!=''" ng-click="removeSearchItem('price')">品牌:{{searchMap.price}}<i class="sui-icon icon-tb-close"></i></li>
				搜索结果:{{resultMap.total}}条
			</ul>
		2. 分析:这里{{resultMap.total}}显示总记录数

	2. 修改2:
		1. 部分代码:
				       <div class="sui-pagination pagination-large">
                    	<ul>
                        <li class="prev disabled">
                            <a href="#">«上一页</a>
                        </li>
                        <li ng-repeat="page in pageLabel">
                            <a href="#">{{page}}</a>
                        </li>
                        <li class="dotted"><span>...</span></li>
                        <li class="next">
                            <a href="#">下一页»</a>
                        </li>
                  	  </ul>
                    <div><span>共{{resultMap.totalPages}}页&nbsp;</span><span>
   								   到第
   					   <input type="text" class="page-num">
   				   页 <button class="page-confirm" onclick="alert(1)">确定</button></span></div>
                </div>
		2. 分析:
			* 这里通过page in pageLabel遍历每个page做出了分页的具体页码选择框;
			* resultMap.totalPages显示了总页数;

分页-- 前端 – 页码查询

1. 页码优化:
	1. 思路:
		1. 如果总页数小于等于5页?
			* --->  显示全部页码

		2. 如果总页数大于5页?
			* 再进一步判断?
				1. if:当前页码小于等于3  --> 显示前5项目
				2. if:当前页码大于总页数-2  -->  显示后5页
				3. else{  -->显示后5页

	2. 代码实现
		1. 修改1:定义firstPage和lastPage:
			1. 部分代码演示:
			
				buildPageLabel=function(){
			        //构建分页状态栏
			        $scope.pageLabel=[];
					var firstPage=1;
					var lastPage=$scope.resultMap.totalPages;		//截止页码
					if($scope.resultMap.totalPages>5){
						if($scope.searchMap.pageNo<=3){
							lastPage=5;
						}else if($scope.searchMap.pageNo>$scope.resultMap.totalPages-2){
							firstPage=$scope.resultMap.totalPages-4;
						}else{
							firstPage=$scope.searchMap.pageNo-2;
							lastPage=$scope.searchMap.pageNo+2;
						}}
			        for(var i=firstPage;i<=lastPage;i++){
			            $scope.pageLabel.push(i);
			        }
			    };

			2. 分析:
				* 之前的分页没有限制页码个数,所以会很不好看;为了优化,所以首先定义了两个变量,一个是起始页码firstPage,一个是结束页码firstPage;
				* 通过对后端传入的总页数进行判断,如果它小于5则按正常的显示即可;
				* 如果大于5且当前页码小于等于3的时候,结束页码就为5;
				* 如果大于5且当前页码小于总页码-2的时候,起始页码为总页码-4;
				* 如果大于5且既不小于等于5又不小于总页码-2的时候,就定义firstPae的值为当前页码-2,lastPage的值为当前页码+2;

		2. 修改2:点击页码搜索查询实现
			1. 部分代码演示:			webapp/js/controller/searchController.js:
				//分页页码搜索
				$scope.queryByPage=function(pageNo){
			    	//将点击事件传入的pageNo传入searchMap对象中,重新进行查询
					$scope.searchMap.pageNo=pageNo;
					$scope.search;		//查询
			
				}
			2. 分析:这里通过点击事件将pageNo传入queryByPage方法,该方法再将该值赋值给$scope.searchMap.pageNo,再重新查询,从而达到查询其他页码的数据的效果;


			3. 部分代码演示:     webapp/search.html:
					1. 
						 <li ng-repeat="page in pageLabel">
                            <a href="#" ng-click="queryByPage(page)">{{page}}</a>
                        </li>

					2.
						<ul>
	                        <li class="prev disabled">
	                            <a href="#" ng-click="queryByPage(searchMap.pageNo-1)">«上一页</a>
	                        </li>
	                        <li ng-repeat="page in pageLabel">
	                            <a href="#" ng-click="queryByPage(page)">{{page}}</a>
	                        </li>
	                        <li class="dotted"><span>...</span></li>
	                        <li class="next">
	                            <a href="#"ng-click="queryByPage(searchMap.pageNo+1))">下一页»</a>
	                        </li>
	                    </ul>
					3. 
						//分页页码搜索
						$scope.queryByPage=function(pageNo){
							//进行pageNo的合法值判断
							if(pageNo<1|| pageNo>$scope.resultMap.totalPages){
								reutrn;
							}
					    	//将点击事件传入的pageNo传入searchMap对象中,重新进行查询
							$scope.searchMap.pageNo=pageNo;
							$scope.search;		//查询
					
						}
			4. 分析:
				1. 代码1中使用点击事件传入page值,可以进行绑定页码搜索查询功能
				2. 代码2中上一页和下一页,使用queryByPage方法传入值进行上下页翻页功能;
				3. 代码3中对分页合法性进行判断,如果值小于1或者大于总页数,则返回一个空,即绑定在上一页和下一页就不会出现错误;当page不合法时候,搜索功能停止了;


2. 页码跳转 :
	1. 部分代码:    webapp/search.html:

  				<div><span>共{{resultMap.totalPages}}页&nbsp;</span><span>
    		  到第  <input type="text" class="page-num" ng-model="searchMap.pageNo"> 页 
			<button class="page-confirm" onclick="alert(1)" ng-click="queryByPage(searchMap.pageNo)">确定</button></span></div>
                </div>

	2. 部分代码:    webapp/js/controller/searchController.js:
					//搜索
			$scope.search=function(){
				//如果有字符串,将其转换为数字
				$scope.searchMap.pageNo=parseInt($scope.searchMap.pageNo);			//转换为数字;
				searchService.search($scope.searchMap).success(
					function(response){
						$scope.resultMap=response;
		                buildPageLabel();		//构建分页状态栏
					}
				);
		
			};

	3. 分析:
		1. search.html中ng-model="searchMap.pageNo"绑定了输入的页码,当点击确定的时候,将传入的页码通过queryByPage方法传入后端进行查询
		2. 因为此时输入的页码数字实际上为字符串,所以应该在searchController.js中的搜索方法进行解析,将字符串的变量解析为数字,传入后端进行查询;

分页-- 前端 – 构建不可用样式

1. 部分代码实现:
	1. webapp/js/controller/searchController.js:
			//判断是否为第一页
			$scope.isTopPage=function(){
				if($scope.searchMap.pageNo==1){
					return true;
				}else{
					return false;
				}
			};
		
			//判断是否为最后一页
			$scope.isEndPage=function(){
				if ($scope.searchMap.pageNo==$scope.resultMap.totalPages){
					return true;
				}else {
					return false;
				}
		
			}

	2. webapp/search.html:

			
				 <ul>
                    <li class="prev {{isTopPage()?'disabled':''}}">
                        <a href="#" ng-click="queryByPage(searchMap.pageNo-1)">  <<  </a>
                    </li>
                    <li ng-repeat="page in pageLabel">
                        <a href="#" ng-click="queryByPage(page)">{{page}}</a>
                    </li>
                    <li class="dotted"><span>...</span></li>
                    <li class="next {{isEndPage()?'disabled':''}}">
                        <a href="#"ng-click="queryByPage(searchMap.pageNo+1))"> >> </a>
                    </li>
                </ul>

3. 分析:
	1. 首先searchController.js中增加了两个方法,一个是判断是否为第一页,一个是判断是否为最后一页;
	2. 其次,在search.html页面中,使用了正则表达式:isTopPage()?'disabled':''   如果是第一页就使用disabled虚化,让点击“上一页”变得不可用了。下面的判断是否为最后一页也是这个道理;

分页 – 前端 – 省略号完善

1. 介绍:页码只显示了五个,所以应该在页码的末尾或者开头有省略号表示还有其他的页码隐藏了;
2. 案例演示:
	1. 部分代码:
		1. webapp/search.html:
			1. 
				<button class="sui-btn btn-xlarge btn-danger" ng-click="searchMap.pageNo=1;search()" type="button">搜索

			2.  
				<ul>
                    <li class="prev {{isTopPage()?'disabled':''}}">
                        <a href="#" ng-click="queryByPage(searchMap.pageNo-1)">  <<  </a>
                    </li>
                    <li class="dotted" ng-if="firstDot==true"><span>...</span></li>
                    <li ng-repeat="page in pageLabel">
                        <a href="#" ng-click="queryByPage(page)">{{page}}</a>
                    </li>
                    <li class="dotted" ng-if="lastDot==true"><span>...</span></li>
                    <li class="next {{isEndPage()?'disabled':''}}">
                        <a href="#"ng-click="queryByPage(searchMap.pageNo+1))"> >> </a>
                    </li>
                </ul>
		2. webapp/js/controller/searchController.js:
				
						buildPageLabel=function(){
			        //构建分页状态栏
			        $scope.pageLabel=[];
					var firstPage=1;		//开始页码
					var lastPage=$scope.resultMap.totalPages;		//截止页码
					$scope.firstDot=true;		//前面有点
					$scope.lastDot=true;			//后面有点
					if($scope.resultMap.totalPages>5){
						if($scope.searchMap.pageNo<=3){
							lastPage=5;
							$scope.firstDot=false;
						}else if($scope.searchMap.pageNo>$scope.resultMap.totalPages-2){
							firstPage=$scope.resultMap.totalPages-4;
							$scope.lastDot=false;
						}else{
							firstPage=$scope.searchMap.pageNo-2;
							lastPage=$scope.searchMap.pageNo+2;
						}
			
					}else {
						$scope.firstDot=false;		//前面有点
						$scope.lastDot=false;		//后边有点
					}
			        for(var i=firstPage;i<=lastPage;i++){
			            $scope.pageLabel.push(i);
			        }  };
		3. 分析:
			1. 首先,在search.html中给搜索按钮绑定pageNo=1,这样使得每次搜索别的关键字的时候可以直接跳转到第一页;不然的话,比如原关键字有商品19页,但是新关键字商品有4页,那么不设置的话就会显示19页的商品,因为新关键字没有19页就会显示为空;
			2. 关键代码: <li class="dotted" ng-if="firstDot==true"><span>...</span></li>和  <li class="dotted" ng-if="lastDot==true"><span>...</span></li> ,他们的作用是当firstDot和lastDot的值为ture的时候才显示"...";
			3. 在searchController.js中,定义了两个变量,当页码小于5的时候,就不显示省略号,因为本来也没有多的页码可以被隐藏了;当小于等于3的时候后面显示省略号,当小于总页码-2的时候,前面显示省略号;

多关键字搜索:

1. 分析:
	* 在日常的电商平台搜索中,可能会遇到多关键字搜索,比如不仅仅搜“手机”,或者“三星”,而是直接"三星手机",我们solr的分词器会将其拆分两个进行关联度并行搜索;但是有些客户会搜索的时候带空格,即"三星    手机",这种情况下会变成多条件搜索,所以我们应该去掉空格,变成并行搜索;
2. 解决方案:
	1. 部分代码演示:service: com.pinyougou.service.impl.ItemSearchServiceImpl.java--> search()方法中增加:
				//空格处理:
	        String keywords=(String)searchMap.get("keywords");
	        searchMap.put("keywords",keywords.replace(" ",""));         //关键字去掉空格

	2. 分析:先获取字符串,然后存入searchMap的时候,先将其replace,将空格替换掉即可;

排序-- 后端:

1. 代码:
	1. 位置:service: com.pinyougou.service.impl.ItemSearchServiceImpl.java:   -->searchList()查询列表方法中增加(它是一个search()方法中提取出去的方法...是search()的一部分)
			  //1.7  排序查询
	        //获取前端的两个变量
	        String sortValue=(String)searchMap.get("sort");         //升序ASC  降序DESC
	        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. 位置:js:  webapp/js/controller/searchController.js:
			$scope.searchMap={'keywords':'','category':'','brand':'','spec':{},'price':'','pageNo':1,'pageSize':40,'sort':'','sortField':''};
2. 分析:
	* 首先在js中的searchController.js中的定义searchMap添加了两个key,value值,一个是sort[排序方式],一个是sortField[要排序的列];
	* 在service中的查询列表中进行了排序,首先接收了两个变量,然后进行判断是否符合哪个排序方法然后再进行排序;

按价格升序,降序,和默认排序-- 前端:

1. 代码: 
	1. 位置:js:  webapp/js/controller/searchController.js:

		//排序查询
		$scope.sortSearch=function (sortFiled,sort) {
			//赋值
			$scope.searchMap.sort=sort;
			$scope.searchMap.sortField=sortField;
	
			//查询
			$scope.search();
	
	
	    }
	2. 位置:search.html:

		  <li class="active">
                <a href="#" ng-click="sortSearch('','')">综合</a>
            </li>
            <li>
                <a href="#">销量</a>
            </li>
            <li>
                <a href="#">新品</a>
            </li>
            <li>
                <a href="#">评价</a>
            </li>
            <li>
                <a href="#" ng-click="sortSearch('price','ASC')">价格↑</a>
            </li>
            <li>
                <a href="#" ng-click="sortSearch('price','DESC')">价格↓</a>
            </li>

2. 分析:
	* 这里在searchController.js中的sortSearch方法将传入的sortField和sort值进行与前面已经定义过的searchMap集合进行绑定;绑定绑定完成后调用查询方法,带着参数查询即可返回已经排序好的商品数据;
	* 在search.html中因为价格有升序降序,所以分成两个进行查询;传入price和ASC或者DESC进行查询,综合是默认界面,就是说不进行任何排序的结果,所以两个值都为空;

按新品排序(上架时间)

1. 代码:
	1. solrhome/connection1/schema.xml:
		* 添加一个新的普通域:
			<field name="item_updatetime" type="date" indexed="true" stored="true" />

	2. pojo/TbItem.java:  
		* 实体类中一个变量添加注解,与域对应
			  @Field("item_updatetime")
  			  private Date updateTime;

	3. search.html
		* 绑定新品:
			 <li>
                <a href="#" ng-click="sortSearch('updatetime','DESC')">新品</a>
            </li>

2. 分析:
	* 首先添加一个域,然后再在实体类中的一个变量添加注解,与sorlhome中的域对应;
	* 前端页面绑定新品,点击事件后传入值,进行新品排序查询;

订单销量和评价排序思路:

1. 订单销量查询:
	* 可以先在solrhome中添加一个域,然后在订单表中统计id值的数量,进行查询;因为订单每分每秒都会有变化,所以最好可以每天更新索引库一次,不必实时更新;因为它只是排序,不需要实时更新,能减轻solr库压力;可以使用spring task:任务调用,让程序自动进行,一般在凌晨进行; 销量:还有日销量,月销量,季度,年等...
2. 评价:
	* 一样可以每天更新一次,需要考虑到好评,差评的存在,比如差评很多的也不应该排在前面;
	* 可以用一个积分累计:比如好评+3分,中评+1分,差评-3分		按积分来进行排序;

隐藏品牌列表

1. 需求:当搜索三星手机的时候,品牌列表应该遍历与关键词的分词进行比较,如果有一样的品牌那么就应该直接屏蔽掉品牌列表;比如我们搜三星手机的时候,品牌列表过滤就应该消失,不再显示品牌的选项;
2. 代码:
	1. 位置:webapp/search.html:
			 <div class="type-wrap" ng-if="resultMap.categoryList!=null && searchMap.category==''&& keywordsIsBrand()==false">
            <div class="fl key">商品分类</div>

	2. 位置:webapp/js/controller/searchController.js:
				//判断关键字是否是品牌列表
				$scope.keywordsIsBrand=function () {
					for (var i=0;i<$scope.resultMap.brandList.length;i++){
						//因为IndexOf是判断是否包含了它,所以结果值是一个数字,返回的是有几个值是含有的,所以需要判断>=0
						if ($scope.searchMap.keywords.indexOf($scope.resultMap.brandList[i].text)>=0){
							return true;
						}
					}
					return false;
			    };

	3. 分析:
		* 首先在js下的searchController.js创建了判断关键字是否是品牌列表方法,对结果返回true或者false,然后绑定品牌的div标签,调用此方法判断是否=false即可控制是否显示品牌列表;

搜索页与首页对接:

1. 思路:传递参数(关键字):首页把关键字传递给搜索页,然后搜索页接收关键字并自动查询;		[静态传参]
2. 代码:
	1. 位置:网站首页    pinyougou-portal-web/webapp/index.html:
			<div class="input-append">
				<input type="text" id="autocomplete" ng-model="keywords" type="text" class="input-error input-xxlarge" />
				<button class="sui-btn btn-xlarge btn-danger" ng-click="search()" type="button">搜索</button>
			</div>
	2. 位置:js:		pinyougou-portal-web/webapp/js/controller/contentController.js:
			//搜索跳转到搜索页
				$scope.search=function () {
					location.href="http://localhost:9104/search.html#?keywords"+$scope.keywords;
			    }
	3. 位置: js:        pinyougou-search-web/webapp/js/controller/searchController.js:
				//加载关键字
			$scope.loadKeywords=function () {
				$scope.searchMap.keywords=$location.search()['keywords'];
				$scope.search();			//查询
		    }
	4. 位置: web:		pinyougou-search-web/webapp/search.html:
			<body ng-app="pinyougou" ng-controller="searchController" ng-init="loadKeywords()">

3. 分析:
	* 首先先通过首页的ng-model将输入的值绑定到keywords,然后再通过contentController.js中的search方法进行跳转并且带上值(静态跳转在angularJS中需要在?前加#号),然后搜索页主体body绑定了loadKeywords()方法,初始化即接收了该值,然后传入js中的searchController.js中的loadKeywords()方法中,将其传入$searchMap.keywords,然后再进行查询,即可满足从首页自动跳转到搜索页并且自动查询的功能;

更新索引库

1. 思路:
	1. 商家商品服务   查询方法,根据SPU的ID集合来查询SKU列表(状态时已审核)
	2. 搜索服务  	批量导入方法:接收参数为SKU列表;
	3. 运营商后台    调用上边的两个方法;

2. 商家商品服务代码:
	1. service:   位置:pinyougou-sellergoods-interface/main/src/java/com/pinyougou/sellergoods/service/GoodsService:			添加部分代码:
			public List<TbItem> findItemListByGoodsIdListAndStatus(Long []goodsIds, String status);
	2. impl: 位置:pinyougou-sellergoods-service/.../impl/GoodsServiceImpl.java:
			/*
			*
			* 根据SPU的id集合和status的状态查询SKU列表
			* */
			public List<TbItem> findItemListByGoodsIdListAndStatus(Long []goodsIds,String status){
				TbItemExample example=new TbItemExample();
				TbItemExample.Criteria criteria=example.createCriteria();
				criteria.andStatusEqualTo(status);
				criteria.andGoodsIdIn(Arrays.asList(goodsIds));			//指定条件:SPU 的ID集合;   这里传入的值是一个数组,所以需要asList方法将其变成集合;
				return itemMapper.selectByExample(example);	
			}

3. 搜索服务--- 导入:
	1. interface:		位置:pinyougou-search-interface...interface/ItemSearchService.java  :
		    /*
		    *
		    * 批量导入
		    * */
		    public void importList(List list);
	2. service:			... impl/ItemSearchServiceImpl.java  :
				
		    @Override
		    public void importList(List list) {
		        solrTemplate.saveBeans(list);
		        solrTemplate.commit();
		    }	
4. 运营商后台:	-- 联合:
	1. 部分代码修改: Controller:		位置:pinyougou-manger-web/.../controller/GoodsController.js:
					//导入ItemSearchService
				@Reference(timeout = 100000)
				private ItemSearchService itemSerchaService;
				
				
				@RequestMapping("/updateStatus")
				public Result updateStatus(Long[] ids,String status){
					try{
						goodsService.updateStatus(ids,status);
						if ("1".equals(status)){
							//如果是审核通过
							//需要导入的SKU列表
							List<TbItem> itemList=goodsService.findItemListByGoodsIdListAndStatus(ids,status);
							//导入到solr:
							itemSerchaService.importList(itemList);
						}
						return new Result(true,"成功");
					}catch (Exception e){
						e.printStackTrace();
						return new Result(false,"失败");
							}
						}
					}
5. 分析:
	* 这里先在商家服务后台设置根据SPU的id集合和status的状态查询SKU列表的方法,然后在搜索服务写-->批量导入方法:接收参数为SKU列表; 当以上两个功能完成之后,在运营商管理后台对商家商品审核的功能模块添加方法,当修改状态updataStatus()方法执行的时候,先判断是否审核通过,如果审核通过,则先将商品的sku列表导入,然后导入到solr中,完成索引库的更新;

删除商品同步

1. 思路:删除一件商品(逻辑删除)的时候,应该也一起将它的索引库一起删除;首先在搜索search-service中和interface中定义删除方法的服务;然后再在运营商删除商品的操作中连带删除索引库,调用service的删除方法;

2. 代码实现:
	1. interface:    pinyougou-interface.../ItemSearchService:
		    /*
		    *
		    * 删除商品列表
		    * */
		    public void deleteByGoodsIds(List goodsIds);
	2. service: 	pinyougou-service.../impl/ItemSearchServiceImpl.java :
		    @Override
		    public void deleteByGoodsIds(List goodsIds) {
		        Query query=new SimpleQuery("");
		        Criteria criteria=new Criteria("item_goodsid").in(goodsIds);
		        query.addCriteria(criteria);
		        solrTemplate.delete(query);
		        solrTemplate.commit();
		    }
	3. web:		pinyougou-manager-web.../controller/GoodsController.java:

				/**
				 * 批量删除
				 * @param ids
				 * @return
				 */
				@RequestMapping("/delete")
				public Result delete(Long [] ids){
					try {
						goodsService.delete(ids);
						//从索引库中删除
						itemSerchaService.deleteByGoodsIds(Arrays.asList(ids));
						return new Result(true, "删除成功"); 
					} catch (Exception e) {
						e.printStackTrace();
						return new Result(false, "删除失败");
					}
				}

3. 分析:
	* 先提供接口和方法,然后在批量删除操作中调用service方法进行删除索引库操作;

猜你喜欢

转载自blog.csdn.net/qq_37128049/article/details/84782621
今日推荐