1. 程式人生 > >Springboot+AngularJS+Spring-data-Solr:搜尋內容匹配高亮顯示

Springboot+AngularJS+Spring-data-Solr:搜尋內容匹配高亮顯示

Java後臺部分:

package com.phubing.search.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.solr.core.SolrTemplate;
import org.springframework.data.solr.core.query.Criteria;
import org.springframework.data.solr.core.query.HighlightOptions;
import org.springframework.data.solr.core.query.HighlightQuery;
import org.springframework.data.solr.core.query.Query;
import org.springframework.data.solr.core.query.SimpleHighlightQuery;
import org.springframework.data.solr.core.query.SimpleQuery;
import org.springframework.data.solr.core.query.result.HighlightEntry;
import org.springframework.data.solr.core.query.result.HighlightEntry.Highlight;
import org.springframework.data.solr.core.query.result.HighlightPage;
import org.springframework.data.solr.core.query.result.ScoredPage;

import com.alibaba.dubbo.config.annotation.Service;
import com.phubing.pojo.TbItem;
import com.phubing.search.service.ItemSearchService;

/**
 * 如果搜尋時間過長,會造成搜尋超時
 * dubbo搜尋時間預設為1秒鐘
 * 併發高或者伺服器效能不夠
 * 可以加上@Service(timeout=3000)註解,設定dubbo超時時間
 * 如果服務方和消費方同時設定了超時時間,dubbo會以消費方的設定為準
 * 
 * @author phubing
 *
 */
@Service(timeout=3000)
public class ItemSearchServiceImpl implements ItemSearchService{
	@Autowired
	private SolrTemplate solrTemplate;
	
	@Override
	public Map<String, Object> search(Map searchMap) {
		Map<String, Object> map = new HashMap<String, Object>();
		
		/*Query query = new SimpleQuery("*:*");
		//is表示匹配
		*//**
		 * {
		 * "keywords":"關鍵字"
		 * }
		 *//*
		Criteria criteria = new Criteria("item_keywords").is(searchMap.get("keywords"));
		query.addCriteria(criteria );
		ScoredPage<TbItem> page = solrTemplate.queryForPage(query, TbItem.class);
		//將當前返回結果返回給rows
		*//**
		 * 返回的格式為
		 * {rows:[]}
		 * 
		 *//*
		map.put("rows", page.getContent());*/
		
		HighlightQuery query = new SimpleHighlightQuery();
		HighlightOptions highlightOptions = new HighlightOptions().addField("item_title");
		//字首
		highlightOptions.setSimplePrefix("<strong style=\'color:red;\'>");
		//字尾
		highlightOptions.setSimplePostfix("</strong>");
		
		//為查詢物件設定高亮選項
		/**
		 * <strong style="color:red;">搜尋關鍵字/詞</strong>
		 */
		query.setHighlightOptions(highlightOptions);
		
		//關鍵字查詢
		Criteria criteria = new Criteria("item_keywords").is(searchMap.get("keywords"));
		query.addCriteria(criteria );
		//返回一個高亮頁物件
		HighlightPage<TbItem> page = solrTemplate.queryForHighlightPage(query, TbItem.class);
		/**
		 * 1、此時可以獲取到一個不經過高亮處理的內容 page.getContent()
		 * 2、需要從高亮入口集合獲取
		 * 3、entryList集合的每個物件,就是每條記錄的內容
		 * 4、HighlightEntry<TbItem>是高亮入口物件,存在一個獲取所有高亮的方法
		 * 5、高亮列表中為何還有一個高亮列表?
		 * 	5.1 HighlightOptions().addField設定高亮列,並且可以建立多個高亮列
		 * 	5.2 建立了多個高亮列就會返回多個高亮列
		 * 6、為何Highlight highlightEntry也是一個高亮列,而不是直接獲取一個高亮值?
		 * 	6.1 每一個域有可能儲存多值,在schema.xml中配置了N個單獨的field,所以每一個高亮列都有其單獨的域
		 * 7、如何讓頁面產生高亮結果?
		 * 	7.1 從高亮列表中獲取高亮列,highlightsList.get(0).getSnipplets().get(0)
		 * 	7.2 將高亮頁賦予結果集page.getContent():item.setTitle(highlightsList.get(0).getSnipplets().get(0));
		 * 
		 */
		//需要從返回高亮物件中獲取高亮結果再返回,即在高亮入口集合中遍歷
		List<HighlightEntry<TbItem>> entryList = page.getHighlighted();
		for (HighlightEntry<TbItem> entry : entryList) {
			//得到一個高亮列表
			List<Highlight> highlightsList = entry.getHighlights();
			//是否還需要遍歷取決於高亮列的個數
			/*for (Highlight highlightEntry : highlightsList) {
				List<String> snippletsList = highlightEntry.getSnipplets();
			}*/
			if(highlightsList.size() > 0 && highlightsList.get(0).getSnipplets().size() > 0) {
				//與page.getContent()是同一個
				TbItem item = entry.getEntity();
				//確定只有一列的情況下
				item.setTitle(highlightsList.get(0).getSnipplets().get(0));
			}
			
		}
		map.put("rows", page.getContent());
		
		return map;
	}
	

}

 

AngularJS中controller層:

/*
Angularjs為了防止(html、js)攻擊,會將後端返回的html程式碼原樣輸出,此時需要採用$sce,即Angularjs信任策略,使用後就會解析後再輸出
trustHtml、trustJs
將過濾服務封裝成通用過濾器
*/
//封裝通用過濾器
app.filter('trustHtml',['$sce', function($sce){
	//傳入的引數就是需要過濾的內容
	return function(data){
		return $sce.trustAsHtml(data);
	}
}]);

 

頁面呼叫:

<div class="attr" ng-bind-html="item.title | trustHtml"></div>