Solr实现商城搜索高亮显示

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdsgdh308227363/article/details/84672660

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;
    }

}
 

猜你喜欢

转载自blog.csdn.net/gdsgdh308227363/article/details/84672660