天天看点

Solr实现商城搜索高亮显示

package com.pinyougou.search.service.impl;
import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Sort;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.data.solr.core.SolrTemplate;
 import org.springframework.data.solr.core.query.Criteria;
 import org.springframework.data.solr.core.query.FilterQuery;
 import org.springframework.data.solr.core.query.GroupOptions;
 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.SimpleFacetQuery;
 import org.springframework.data.solr.core.query.SimpleFilterQuery;
 import org.springframework.data.solr.core.query.SimpleHighlightQuery;
 import org.springframework.data.solr.core.query.SimpleQuery;
 import org.springframework.data.solr.core.query.result.GroupEntry;
 import org.springframework.data.solr.core.query.result.GroupPage;
 import org.springframework.data.solr.core.query.result.GroupResult;
 import org.springframework.data.solr.core.query.result.HighlightEntry;
 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.alibaba.fastjson.JSON;
 import com.pinyougou.pojo.TbItem;
 import com.pinyougou.search.service.ItemSearchService;/**
  * 搜索serviceimpl
  * 
  * @author Administrator
  *
  */
 @SuppressWarnings("all")
 @Service(timeout = 10000)
 public class ItemSearchServiceImpl implements ItemSearchService {    @Autowired
     private SolrTemplate solrTemplate;    /**
      * 搜索
      */
     @Override
     public Map<String, Object> search(Map searchMap) {        Map<String, Object> map = new HashMap<>();
         Query query = new SimpleQuery();
         Criteria criteria = new Criteria("item_keywords").is(searchMap.get("keywords"));
         query.addCriteria(criteria);
         ScoredPage<TbItem> page = solrTemplate.queryForPage(query, TbItem.class);
         map.put("rows", page.getContent());        return map;
     }    /**
      * 搜索高亮显示
      * 
      * @param searchMap
      * @return
      */
     @Override
     public Map<String, Object> searchHighlight(Map searchMap) {
         Map<String, Object> map = new HashMap<>();
         map.putAll(searchMap(searchMap));
         List categoryList = searchCategoryList(searchMap);
         map.put("categoryList", categoryList);        // 查看是否传入了商品分类
         String category = (String) searchMap.get("category");
         if (category != "") {// 如果有商品分类(注意:商品分类只能选一个),那就按照商品分类返回规格和品牌
             map.putAll(searchBrandAndSpecList(category));
         } else {
             if (categoryList.size() > 0) {
                 map.putAll(searchBrandAndSpecList((String) categoryList.get(0)));
             }
         }        return map;
     }    /**
      * 返回值也可以是List,Map更易于扩展
      * 
      * @param searchMap
      * @return
      */
     private Map searchMap(Map searchMap) {
         Map<String, Object> map = new HashMap<>();
         // 高亮显示设置
         HighlightQuery query = new SimpleHighlightQuery();
         HighlightOptions highlightOptions = new HighlightOptions().addField("item_title");// 设置高亮字段
         highlightOptions.setSimplePrefix("<em style='color:red'>");// 设置高亮前缀
         highlightOptions.setSimplePostfix("</em>");// 设置高亮后缀
         query.setHighlightOptions(highlightOptions);// 设置高亮选项        // 1、按照关键字查询(关键字有可能被用户在中间加入空格,所以要去空格)
         String keywords = (String) searchMap.get("keywords");
         searchMap.put("keywords", keywords.replace(" ", ""));//取出所有空格
         Criteria criteria = new Criteria("item_keywords").is(searchMap.get("keywords"));
         query.addCriteria(criteria);         // 2、按照商品分类查询
         if (!"".equals(searchMap.get("category"))) {
             Criteria filterCriteria = new Criteria("item_category").is(searchMap.get("category"));
             FilterQuery filterQuery = new SimpleFilterQuery(filterCriteria);
             query.addFilterQuery(filterQuery);
         }         // 3、按照品牌查询
         if (!"".equals(searchMap.get("brand"))) {
             Criteria filterCriteria = new Criteria("item_brand").is(searchMap.get("brand"));
             FilterQuery filterQuery = new SimpleFilterQuery(filterCriteria);
             query.addFilterQuery(filterQuery);
         }         // 4、按照规格查询
         if (searchMap.get("spec") != null) {
             Map<String, String> specMap = (Map) searchMap.get("spec");
             for (String key : specMap.keySet()) {
                 Criteria filterCriteria = new Criteria("item_spec_" + key).is(specMap.get(key));
                 FilterQuery filterQuery = new SimpleFilterQuery(filterCriteria);
                 query.addFilterQuery(filterQuery);
             }
         }         // 5、按照价格区间查询
         if (!"".equals(searchMap.get("price"))) {            String[] price =((String) searchMap.get("price")).split("-");
            if(!price[0].equals("0")){//最低价格不是0,最低价格就是price[0]
                 Criteria filterCriteria=new Criteria("item_price").greaterThanEqual(price[0]);
                 FilterQuery filterQuery=new SimpleFilterQuery(filterCriteria);
                 query.addFilterQuery(filterQuery); 
             }            if(!price[1].equals("*")){//最高价格不是*,最高价格就是price[1]
                 Criteria filterCriteria=new Criteria("item_price").lessThanEqual(price[1]);
                 FilterQuery filterQuery=new SimpleFilterQuery(filterCriteria);
                 query.addFilterQuery(filterQuery); 
             }        }
         // 6、分页查询
         Integer pageNo = (Integer) searchMap.get("pageNo");//获取前端传入的查询第几页的页码
         if(pageNo == null){//如果没有传入值,默认为1
             pageNo = 1;
         }
         Integer pageSize = (Integer) searchMap.get("pageSize");//每页查询多少条
         if(pageSize == null){//如果没有传入值,默认为20
             pageSize = 20;
         }
         query.setOffset((pageNo-1)*pageSize);//从第几条记录查询
         query.setRows(pageSize);         //7、按照升降序条件查询
         String sortValue = (String) searchMap.get("sort");
         String sortField = (String) searchMap.get("sortField");        if(sortField != null && !sortField.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);
             }        }
        // 根据条件查询,返回高亮显示结果
         HighlightPage<TbItem> page = solrTemplate.queryForHighlightPage(query, TbItem.class);        // 高亮显示获取结果
         for (HighlightEntry<TbItem> h : page.getHighlighted()) {// 循环高亮入口集合
             TbItem item = h.getEntity();
             if (h.getHighlights().size() > 0 && h.getHighlights().get(0).getSnipplets().size() > 0) {
                 item.setTitle(h.getHighlights().get(0).getSnipplets().get(0));// 设置高亮显示结果。因为只有一个高亮域“.addField("item_title")”,所以不需要遍历,直接取第一个
             }
         }        map.put("rows", page.getContent());
        map.put("totalPages", page.getTotalPages());//返回总页数
         map.put("total", page.getTotalElements());//返回总记录数
         return map;
     }    /**
      * 查询分类列表
      * 
      * @param searchMap
      * @return
      */
     private List searchCategoryList(Map searchMap) {        List<String> list = new ArrayList();
        Query query = new SimpleQuery();
         // 按照关键字查询
         Criteria criteria = new Criteria("item_keywords").is(searchMap.get("keywords"));
         query.addCriteria(criteria);        // 设置分组选项
         GroupOptions groupOptions = new GroupOptions().addGroupByField("item_category");
         query.setGroupOptions(groupOptions);        // 得到分组页
         GroupPage<TbItem> page = solrTemplate.queryForGroupPage(query, TbItem.class);        // 根据列得到分组结果集(这个域必须要是上面关键字查询集合中的一个,应为上面有可能有多个,这里是分开查询的,一个字段对应一个解决)
         GroupResult<TbItem> groupResult = page.getGroupResult("item_category");        // 得到分页结果入口页
         Page<GroupEntry<TbItem>> groupEntries = groupResult.getGroupEntries();        // 得到分组入口集合
         List<GroupEntry<TbItem>> content = groupEntries.getContent();        for (GroupEntry<TbItem> entry : content) {
             list.add(entry.getGroupValue());// 将分组结果的名称分装到返回值中
         }
         return list;
     }    @Autowired
     private RedisTemplate redisTemplate;    /**
      * 查询品牌和规格列表(从缓存中获取数据)
      * 
      * @param category
      * @return
      */
     private Map searchBrandAndSpecList(String category) {        Map map = new HashMap();
        // 1、先从Redis中根据商品分类名称获取模版ID
         Long templateId = (Long) redisTemplate.boundHashOps("itemCat").get(category);        if (templateId != null) {
            // 2、根据模版ID获取品牌列表
             List brandList = (List) redisTemplate.boundHashOps("brandList").get(templateId);
             map.put("brandList", brandList);            // 3、根据模版ID获取规格列表
             List specList = (List) redisTemplate.boundHashOps("specList").get(templateId);
             map.put("specList", specList);
         }        return map;
     }}      

继续阅读