package com.pinyougou.search.service.impl;
import com.alibaba.dubbo.config.annotation.Service;
import com.pinyougou.pojo.TbItem;
import com.pinyougou.search.service.ItemSearchService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.solr.core.SolrTemplate;
import org.springframework.data.solr.core.query.*;
import org.springframework.data.solr.core.query.result.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service(timeout = 5000)
public class ItemSearchServiceImpl implements ItemSearchService {
@Autowired
private SolrTemplate solrTemplate;
@Override
public Map<String, Object> search(Map searchMap) {
//装在搜索结果的map对象
Map<String, Object> map = new HashMap<>();
/*//从solr服务器上搜索数据
Query query = new SimpleQuery("*:*");
Criteria criteria = new Criteria("item_keywords").is(searchMap.get("keywords"));
query.addCriteria(criteria);
//从solr搜索回来的数据只有部分字段,所以只能填充TbItem的部分字段,未填充的就是null
ScoredPage<TbItem> page = solrTemplate.queryForPage(query, TbItem.class);*/
//1、获取高亮的商品列表
map.putAll(searchList(searchMap));
2、分组查询 关键词所属的商品分类列表
List<String> categoryList = searchCategoryList(searchMap);
map.put("categoryList", categoryList);
//3、根据分类,查询品牌和规格列表
// ,默认显示第一个分类下面的品牌和规格
if(categoryList.size()>0){
//前端只输入了关键字,需要后端返回关键字所属的分类列表,默认显示第一个分类下的品牌和规格列表
map.putAll(searchBrandAndSpecList(categoryList.get(0)));
}
return map;
}
@Autowired
private RedisTemplate redisTemplate;
/**
* 根据分类名在redis中查找对应的品牌列表和规格列表
* @param category
* @return
*/
private Map searchBrandAndSpecList(String category) {
//已知分类名称,搜索对应的品牌和规格,用的是SpringdataRedis存储的
Map map = new HashMap();
//1.根据商品分类名称得到模板ID (这里的数据是在运营商管理时加入缓存的)
Long templateId =(Long) redisTemplate.boundHashOps("itemCat").get(category);
if(templateId!=null){
//根据模板id,查找对应的品牌列表
List brandList = (List)redisTemplate.boundHashOps("brandList").get(templateId);
System.out.println("品牌列表的条数为:"+brandList.size());
//返回值添加品牌列表
map.put("brandList", brandList);
//根据模板id,查找对应的规格选项,对应的是`tb_type_template`这个表
List specList = (List)redisTemplate.boundHashOps("specList").get(templateId);
System.out.println("规格列表的条数为:"+specList.size());
map.put("specList", specList);
}
return map;
}
/**
* 设置高亮
* @param searchMap
* @return
*/
private Map searchList(Map searchMap) {
Map map = new HashMap();
HighlightQuery query = new SimpleHighlightQuery();
HighlightOptions highlightOptions = new HighlightOptions();
//设置需要高亮的域(字段)
highlightOptions.addField("item_title");
//设置高亮的前缀
highlightOptions.setSimplePrefix("<em style='color:red'>");
//设置高亮的后缀
highlightOptions.setSimplePostfix("</em>");
//将高亮的选项的设置装入query对象
query.setHighlightOptions(highlightOptions);
//1.1按照关键字查询所有符合条件的商品对象
Criteria criteria = new Criteria("item_keywords").is(searchMap.get("keywords"));
query.addCriteria(criteria);
//1.2 按商品分类过滤
//如果用户选择了分类
if(!"".equals(searchMap.get("category")) ) {
FilterQuery filterQuery=new SimpleFilterQuery();
Criteria filterCriteria=new Criteria("item_category").is(searchMap.get("category"));
filterQuery.addCriteria(filterCriteria);
query.addFilterQuery(filterQuery);
}
//1.3 按品牌过滤
//如果用户选择了品牌
if(!"".equals(searchMap.get("brand")) ) {
FilterQuery filterQuery=new SimpleFilterQuery();
Criteria filterCriteria=new Criteria("item_brand").is(searchMap.get("brand"));
filterQuery.addCriteria(filterCriteria);
query.addFilterQuery(filterQuery);
}
//1.4 按规格过滤
if(searchMap.get("spec")!=null){
Map<String,String> specMap= (Map<String, String>) searchMap.get("spec");
for(String key :specMap.keySet()){
FilterQuery filterQuery=new SimpleFilterQuery();
Criteria filterCriteria=new Criteria("item_spec_"+key).is( specMap.get(key) );
filterQuery.addCriteria(filterCriteria);
query.addFilterQuery(filterQuery);
}
}
//1.5按价格筛选
if(!"".equals(searchMap.get("price"))){
String[] price = ((String) searchMap.get("price")).split("-");
if(!"0".equals(price[0])){
Criteria filterCriteria=new Criteria("item_price").greaterThanEqual(price[0]);
FilterQuery filterQuery=new SimpleFilterQuery(filterCriteria);
query.addFilterQuery(filterQuery);
}
//如果区间终点不等于*
if(!"*".equals(price[1])){
Criteria filterCriteria=new Criteria("item_price").lessThanEqual(price[1]);
FilterQuery filterQuery=new SimpleFilterQuery(filterCriteria);
query.addFilterQuery(filterQuery);
}
}
//1.6分页查询
//提取页码
Integer pageNo= (Integer) searchMap.get("pageNo");
if(pageNo==null){
//默认第一页
pageNo=1;
}
//获取每页记录数
Integer pageSize=(Integer) searchMap.get("pageSize");
if(pageSize==null){
//默认每页 20条
pageSize=20;
}
//设置solr搜索的从第几条开始展示
query.setOffset((pageNo-1)*pageSize);
query.setRows(pageSize);
//*********** 获取高亮结果集 ***********
//获得高亮页面对象
//获得高亮页对象,包含所有的高亮记录,一条记录为一个TbItem
HighlightPage<TbItem> queryForHighlightPage = solrTemplate.queryForHighlightPage(query, TbItem.class);
//获取所有的高亮记录,也就是所有的商品组成记录组成的list
List<HighlightEntry<TbItem>> highlighted = queryForHighlightPage.getHighlighted();
//循环高亮入口,获取每一条记录
for (HighlightEntry<TbItem> h : highlighted) {
//获取记录中的实体类
TbItem item = h.getEntity();
//h.getHighlights() 获取每条高亮记录的所有高亮域
// h.getHighlights().get(0).getSnipplets()获取第一个高亮域的内容
// h.getHighlights().get(0).getSnipplets().get(0) 一个高亮域中可能存在多值
List<HighlightEntry.Highlight> highlights = h.getHighlights();
List<String> snipplets = highlights.get(0).getSnipplets();
if (highlights.size() > 0 && h.getHighlights().get(0).getSnipplets().size() > 0) {
//设置高亮域的结果
//item.setTitle(h.getHighlights().get(0).getSnipplets().get(0));
item.setTitle(snipplets.get(0));
System.out.println(h.getHighlights().get(0).getSnipplets().get(0));
}
}
/**
* h.getHighlights() 获取每条高亮记录的所有高亮域
* 在new HighlightOptions().addField("item_title")是添加的高亮域
* h.getHighlights().get(0).getSnipplets()获取第一个高亮域的内容
* h.getHighlights().get(0).getSnipplets().get(0) 一个高亮域中可能存在多值
* 取决于solr中的配置域的是否配置了multiValued是否为true
*/
//不进行如上操作,获取的是原生的对象,即是没有经过高亮处理的对象
map.put("rows", queryForHighlightPage.getContent());
//返回总页数
map.put("totalPages", queryForHighlightPage.getTotalPages());
//返回总记录数
map.put("total", queryForHighlightPage.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> pages = solrTemplate.queryForGroupPage(query, TbItem.class);
//根据列得到分组结果集
GroupResult<TbItem> groupResult = pages.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;
}
}