1.高亮显示
@Autowired
private SolrTemplate solrTemplate;
@Override
public Map<String, Object> searchItem(Map<String, Object> searchMap) {
//简单查询开始----------------------------------------------
// Query query = new SimpleQuery("*:*");
// // 构建查询条件
// String keywords = (String) searchMap.get("keywords");
// Criteria criteria = new Criteria("item_keywords").is(keywords);
// query.addCriteria(criteria);
// // 执行查询
// ScoredPage<TbItem> pageResult = solrTemplate.queryForPage(query, TbItem.class);
// // 返回查询结果
// Map<String, Object> resultMap = new HashMap<String, Object>();
// resultMap.put("rows", pageResult.getContent());
//简单查询结束----------------------------------------------
//高亮显示查询开始-------------------------------------------
// 构建高亮域选项
HighlightQuery query = new SimpleHighlightQuery();
HighlightOptions highlightOptions = new HighlightOptions().addField("item_title");// 设置高亮域
highlightOptions.setSimplePrefix("<em style='color:red'>");// 高亮前缀
highlightOptions.setSimplePostfix("</em>");// 高亮后缀
query.setHighlightOptions(highlightOptions);
// 设置查询条件
String keywords = (String) searchMap.get("keywords");
Criteria criteria = new Criteria("item_keywords").is(keywords);
query.addCriteria(criteria);
// 执行查询
HighlightPage<TbItem> pageResult = solrTemplate.queryForHighlightPage(query, TbItem.class);
// 获取高亮入口集合
List<HighlightEntry<TbItem>> entrys = pageResult.getHighlighted();
for (HighlightEntry<TbItem> highlightEntry : entrys) {
// 获取所有高亮域
List<Highlight> highlights = highlightEntry.getHighlights();
// for (Highlight highlight : highlights) {
// 可能存在多值
// List<String> snipplets = highlight.getSnipplets();
// }
// 得到第一个域的第一个值得高亮
if (highlights != null && highlights.size() > 0 && highlights.get(0).getSnipplets() != null
&& highlights.get(0).getSnipplets().size() > 0) {
TbItem entity = highlightEntry.getEntity();
String highlightTitle = highlights.get(0).getSnipplets().get(0);
entity.setTitle(highlightTitle);
}
}
//高亮显示查询结束-------------------------------------------
Map<String, Object> resultMap = new HashMap<String, Object>();
resultMap.put("rows", pageResult.getContent());
return resultMap;
}
2.分组查询
private List<String> searchGroupByCategory(Map<String, Object> searchMap) {
List<String> searchList = new ArrayList<String>();
// 构建分页 group by
Query query = new SimpleQuery("*:*");
GroupOptions GroupOptions = new GroupOptions().addGroupByField("item_category");
query.setGroupOptions(GroupOptions);
// 构建关键字查询 where
Criteria criteria = new Criteria("item_keywords").is(searchMap.get("keywords"));
query.addCriteria(criteria);
// 执行查询,获取分组页对象
GroupPage<TbItem> groupPage = solrTemplate.queryForGroupPage(query, TbItem.class);
// 获取item_category的分组结果
GroupResult<TbItem> groupResult = groupPage.getGroupResult("item_category");
// 获取分页入口页
Page<GroupEntry<TbItem>> groupEntries = groupResult.getGroupEntries();
// 获取分组结果集
List<GroupEntry<TbItem>> content = groupEntries.getContent();
for (GroupEntry<TbItem> groupEntry : content) {
String groupValue = groupEntry.getGroupValue();// 手机 电脑 衣服
searchList.add(groupValue);
}
return searchList;
}
3.过滤字段
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
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.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.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.HighlightEntry.Highlight;
import org.springframework.data.solr.core.query.result.HighlightPage;
import com.alibaba.dubbo.config.annotation.Service;
import com.pinyougou.pojo.TbBrand;
import com.pinyougou.pojo.TbItem;
import com.pinyougou.pojo.TbSpecification;
import com.pinyougou.search.service.ItemSearchService;
/**
* 索引库管理 Service
*
* @author Administrator
*
*/
@Service
public class ItemSearchServiceImpl implements ItemSearchService {
@Autowired
private SolrTemplate solrTemplate;
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Override
public Map<String, Object> searchItem(Map<String, Object> searchMap) {
// 创建返回对象
Map<String, Object> resultMap = new HashMap<String, Object>();
// 1.高亮显示查询
Map<String, Object> highlightMap = searchHighlight(searchMap);
resultMap.putAll(highlightMap);
// 2.分组查询
List<String> categoryList = searchGroupByCategory(searchMap);
resultMap.put("categoryList", categoryList);
// 3.根据分组查询出的分类名称查询规格和品牌列表
String category = (String) searchMap.get("category");
if (StringUtils.isNotBlank(category)) {
// 用户点击了分类
Map<String, Object> brandListAndSpecList = searchBrandListAndSpecList(category);
resultMap.putAll(brandListAndSpecList);
} else {
// 初始化分类名称,获取第一个分类名称进行查询
if (categoryList != null && categoryList.size() > 0) {
Map<String, Object> brandListAndSpecList = searchBrandListAndSpecList(categoryList.get(0));
resultMap.putAll(brandListAndSpecList);
}
}
return resultMap;
}
/**
* 高亮显示查询
*/
@SuppressWarnings("all")
private Map<String, Object> searchHighlight(Map<String, Object> searchMap) {
// 1.1 构建高亮域选项
HighlightQuery query = new SimpleHighlightQuery();
HighlightOptions highlightOptions = new HighlightOptions().addField("item_title");// 设置高亮域
highlightOptions.setSimplePrefix("<em style='color:red'>");// 高亮前缀
highlightOptions.setSimplePostfix("</em>");// 高亮后缀
query.setHighlightOptions(highlightOptions);
// 1.2 设置查询条件
String keywords = (String) searchMap.get("keywords");
Criteria criteria = new Criteria("item_keywords").is(keywords);
query.addCriteria(criteria);
// 1.3 设置分类过滤
if (StringUtils.isNotBlank((String) searchMap.get("category"))) {
Criteria categoryCriteria = new Criteria("item_category").is(searchMap.get("category"));
FilterQuery filterQuery = new SimpleFilterQuery().addCriteria(categoryCriteria);
query.addFilterQuery(filterQuery);
}
// 1.4 设置品牌过滤
if (StringUtils.isNotBlank((String) searchMap.get("brand"))) {
Criteria brandCriteria = new Criteria("item_brand").is(searchMap.get("brand"));
FilterQuery filterQuery = new SimpleFilterQuery().addCriteria(brandCriteria);
query.addFilterQuery(filterQuery);
}
// 1.5 设置规格选项过滤(数据格式 Map 动态域)
if (searchMap.get("spec") != null) {
Map<String, String> specMap = (Map<String, String>) searchMap.get("spec");
for (String key : specMap.keySet()) {
Criteria specCriteria = new Criteria("item_spec_" + key).is(specMap.get(key));
FilterQuery filterQuery = new SimpleFilterQuery().addCriteria(specCriteria);
query.addFilterQuery(filterQuery);
}
}
// 1.6 执行查询并处理结果
HighlightPage<TbItem> pageResult = solrTemplate.queryForHighlightPage(query, TbItem.class);
// 获取高亮入口集合
List<HighlightEntry<TbItem>> entrys = pageResult.getHighlighted();
for (HighlightEntry<TbItem> highlightEntry : entrys) {
// 获取所有高亮域
List<Highlight> highlights = highlightEntry.getHighlights();
// for (Highlight highlight : highlights) {
// 可能存在多值
// List<String> snipplets = highlight.getSnipplets();
// }
// 得到第一个域的第一个值得高亮
if (highlights != null && highlights.size() > 0 && highlights.get(0).getSnipplets() != null
&& highlights.get(0).getSnipplets().size() > 0) {
TbItem entity = highlightEntry.getEntity();
String highlightTitle = highlights.get(0).getSnipplets().get(0);
entity.setTitle(highlightTitle);
}
}
// 1.4 结果返回
Map<String, Object> resultMap = new HashMap<String, Object>();
resultMap.put("rows", pageResult.getContent());
return resultMap;
}
/**
* 分组查询
*/
private List<String> searchGroupByCategory(Map<String, Object> searchMap) {
List<String> searchList = new ArrayList<String>();
// 2.1 构建分页 group by
Query query = new SimpleQuery("*:*");
GroupOptions GroupOptions = new GroupOptions().addGroupByField("item_category");
query.setGroupOptions(GroupOptions);
// 2.2 构建关键字查询 where
Criteria criteria = new Criteria("item_keywords").is(searchMap.get("keywords"));
query.addCriteria(criteria);
// 2.3 执行查询,并处理结果
GroupPage<TbItem> groupPage = solrTemplate.queryForGroupPage(query, TbItem.class);
// 获取item_category的分组结果
GroupResult<TbItem> groupResult = groupPage.getGroupResult("item_category");
// 获取分页入口页
Page<GroupEntry<TbItem>> groupEntries = groupResult.getGroupEntries();
// 获取分组结果集
List<GroupEntry<TbItem>> content = groupEntries.getContent();
for (GroupEntry<TbItem> groupEntry : content) {
String groupValue = groupEntry.getGroupValue();// 手机 电脑 衣服
searchList.add(groupValue);
}
// 2.4 结果返回
return searchList;
}
/**
* 加载品牌列表和规格列表
*/
@SuppressWarnings("unchecked")
private Map<String, Object> searchBrandListAndSpecList(String categoryName) {
Map<String, Object> resultMap = new HashMap<String, Object>();
// 3.1 根据分类名称从缓存中获取模板ID
Object typeTemplateId = redisTemplate.boundHashOps("itemCat").get(categoryName);
if (typeTemplateId != null) {
// 3.2 根据模板ID查询从缓存中获取品牌列表
List<TbBrand> brandList = (List<TbBrand>) redisTemplate.boundHashOps("brandList").get(typeTemplateId);
// 3.3 根据模板ID查询从缓存中获取规格列表
List<TbSpecification> specList =
(List<TbSpecification>) redisTemplate.boundHashOps("specList").get(typeTemplateId);
// 3.4 组装返回结果
resultMap.put("brandList", brandList);
resultMap.put("specList", specList);
}
return resultMap;
}
}
4.区间过滤
// 1.6 价格区间过滤
if (StringUtils.isNotBlank((String) searchMap.get("price"))) {
String[] price = ((String) searchMap.get("price")).split("-");
if (!"0".equals(price[0])) {// 最小价格不等于0
Criteria priceCriteria = new Criteria("item_price").greaterThanEqual(price[0]);
FilterQuery filterQuery = new SimpleFilterQuery().addCriteria(priceCriteria);
query.addFilterQuery(filterQuery);
}
if (!"*".equals(price[1])) {// 不等于最大价格,不做限制
Criteria priceCriteria = new Criteria("item_price").lessThanEqual(price[1]);
FilterQuery filterQuery = new SimpleFilterQuery().addCriteria(priceCriteria);
query.addFilterQuery(filterQuery);
}
}
5.问题:关键字中有空格查询不出结果:
需要对关键字进行预处理
6.排序
// 1.8 排序
String sortField = (String) searchMap.get("sortField");// 需要排序的字段
String sort = (String) searchMap.get("sort");// 升序 ASC 降序 DESC
if (StringUtils.isNotBlank(sortField)) {
if ("ASC".equals(sort)) {
query.addSort(new Sort(Sort.Direction.ASC, sortField));
}
if ("DESC".equals(sort)) {
query.addSort(new Sort(Sort.Direction.DESC, sortField));
}
}