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>