⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 blog.csdn.net/qq_42514129/article/details/84891115 「qq_42514129」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

摘要: 原创出处 http://www.iocoder.cn/Solr/install/ 「芋道源码」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

package com.baidu.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.domain.Sort.Direction;
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 org.springframework.data.solr.core.query.result.ScoredPage;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.baidu.pojo.TbItem;
import com.baidu.pojo.TbSpecificationOption;
import com.baidu.search.service.ItemSearchService;

@Service
public class ItemSearchServiceImpl implements ItemSearchService {

@Autowired
private SolrTemplate solrTemplate;

@Autowired
private RedisTemplate redisTemplate;

private Long totalElements;
private int totalPages;

/**
* 所有的查询
*/
@Override
public Map searchMap(Map<String, String> map) {
// TODO Auto-generated method stub
// 先判断map是否为空
if (map != null && map.get("keywords") != null && !map.get("keywords").trim().equals("")) {
Map resultMap = new HashMap();
// 高亮查询
List highlightList = searchHighlight(map);
resultMap.put("rows", highlightList);
// 分组查询
List categoryList = searchCategory(map);
resultMap.put("categoryList", categoryList);
// 根据分类名称查询模板ID
if (categoryList != null && categoryList.size() > 0) {
Long typeId = (Long) redisTemplate.boundHashOps("itemCatList").get(categoryList.get(0));
// 品牌查询
List brandList = searchBrandList(typeId);
resultMap.put("brandList", brandList);
// 规格选项查询
List specList = searchSpecList(typeId);
resultMap.put("specList", specList);
resultMap.put("totalElements", totalElements);
resultMap.put("totalPages", totalPages);
System.out.println("totalElements" + totalElements);
System.out.println("totalPages" + totalPages);
}

return resultMap;
}
// 根据关键字查询,必须要有关键字,否则前台给出提示
return null;
}

/**
* 分组查询
*
* @param map
* @return
*/
private List searchCategory(Map<String, String> map) {
List list = new ArrayList();
Query query = new SimpleQuery("*:*");
// 添加过滤查询
FilterQuery filterQuery = addFilterQuery(map);
query.addFilterQuery(filterQuery);
// 设置查询条件
Criteria criteria = new Criteria("item_keywords").contains(map.get("keywords"));
GroupOptions options = new GroupOptions().addGroupByField("item_category");
query.setGroupOptions(options);
// 执行查询,得到所有的分组数据
GroupPage<TbItem> groupPage = solrTemplate.queryForGroupPage(query, TbItem.class);
// 有可能指定了多个分组,所以根据指定的分组来获取分组结果
GroupResult<TbItem> groupResult = groupPage.getGroupResult("item_category");
// 获取分组入口对象
Page<GroupEntry<TbItem>> groupEntries = groupResult.getGroupEntries();
for (GroupEntry<TbItem> entry : groupEntries) {
String groupValue = entry.getGroupValue();
if (groupValue != null && !groupValue.equals("")) {
list.add(groupValue);
}
}

return list;
}

/**
* 高亮查询 + 分页结果 + 排序
*
* @param map
* @return
*/
private List searchHighlight(Map<String, String> map) {
Map highlightMap = new HashMap();
// 创建高亮查询对象
HighlightQuery query = new SimpleHighlightQuery();
query = addScoredPage(query, map);
query = addSort(query, map);
// 添加过滤查询
FilterQuery filterQuery = addFilterQuery(map);
query.addFilterQuery(filterQuery);
// 设置高亮显示的域
HighlightOptions options = new HighlightOptions().addField("item_title");
// 设置高亮前缀,后缀
options.setSimplePrefix("<em style='color:red'>");
options.setSimplePostfix("</em>");
// 绑定高亮域跟高亮查询
query.setHighlightOptions(options);
// 创建查询条件
Criteria criteria = new Criteria("item_keywords").contains(map.get("keywords"));
query.addCriteria(criteria);
HighlightPage<TbItem> highlightPage = solrTemplate.queryForHighlightPage(query, TbItem.class);
List<HighlightEntry<TbItem>> highlighted = highlightPage.getHighlighted(); // 高亮入口集合
for (HighlightEntry<TbItem> highlightEntry : highlighted) {
// 遍历高亮入口集合,得到高亮入口对象
TbItem entity = highlightEntry.getEntity(); // 获取原实体对象,需要往原实体对象的title中设置高亮数据
List<Highlight> highlights = highlightEntry.getHighlights();
// 获取单个document中的所有高亮数据集合,因为有可能HighlightOptions().addField("item_title")不只addFiled一个域
if (highlights != null && highlights.size() > 0) {
// 默认选中第一个域,即item.title
Highlight highlight = highlights.get(0);// 终于得到了一个高亮对象,但是有可能这条数据多次匹配了高亮数据,比如搜索手机,苹果手机 防水手机
if (highlight.getSnipplets() != null && highlight.getSnipplets().size() > 0) {
String title = highlight.getSnipplets().get(0);
System.out.println(title);
// 设置高亮结果
entity.setTitle(title); // 由于这是引用数据类型,在查询结果内部进行修改,那么原参数自然会被修改
}
}

}
totalElements = highlightPage.getTotalElements();
totalPages = highlightPage.getTotalPages();
return highlightPage.getContent();
}

/**
* 过滤查询
*
* @param map
* @return
*/
private FilterQuery addFilterQuery(Map map) {
// 创建过滤查询对象
FilterQuery query = new SimpleQuery();
// 过滤分类
String category = (String) map.get("category");
if (category != null && category.trim().length() > 0) {
// 说明不为空,过滤一下
Criteria criteria = new Criteria("item_category").contains(category);
query.addCriteria(criteria);
}
// 过滤品牌
String brand = (String) map.get("brand");
if (brand != null && brand.trim().length() > 0) {
// 说明不为空,过滤一下
Criteria criteria = new Criteria("item_brand").contains(brand);
query.addCriteria(criteria);
}
// 过滤规格选项
Map<String, String> specMap = (Map) map.get("spec");
if (specMap != null && specMap.size() > 0) {
// 说明不为空,过滤一下

for (String key : specMap.keySet()) {
Criteria criteria = new Criteria("item_spec_" + key).contains(specMap.get(key));
query.addCriteria(criteria);
}
}
// 过滤价格区间
String price_str = (String) map.get("price");
if (price_str != null && price_str.trim().length() > 0) {
// 说明不为空,过滤一下, 0-1000 1000-2000 3000-*
String[] strs = price_str.split("-");
if (!strs[0].equals("0")) {
// 说明不是0-1000,应该有下限
Criteria criteria = new Criteria("item_price").greaterThan(strs[0]);
query.addCriteria(criteria);
}
if (!strs[1].equals("*")) {
// 说明不是3000-*,说明应该有上限
Criteria criteria = new Criteria("item_price").lessThan(strs[1]);
query.addCriteria(criteria);
}
}
return query;
}

/**
* 添加商品分类
*
* @param t
* @param map
* @return
*/
private <T> T addScoredPage(T t, Map map) {
Integer currentPage = Integer.parseInt((String) map.get("currentPage"));
Integer size = Integer.parseInt((String) map.get("size"));

if (t instanceof SimpleQuery) {
// 分页查询
SimpleQuery query = (SimpleQuery) t;
if (currentPage == -1) {
currentPage = 1;
}
if (size == -1) {
size = 10;
}
query.setOffset((currentPage - 1) * size);// 计算出当前的页码
query.setRows(size);// 每页显示条数
}
if (t instanceof SimpleHighlightQuery) {
// 分页查询
SimpleHighlightQuery query = (SimpleHighlightQuery) t;
if (currentPage == -1) {
currentPage = 1;
}
if (size == -1) {
size = 10;
}
query.setOffset((currentPage - 1) * size);// 计算出当前的页码
query.setRows(size);// 每页显示条数
}

return t;
}

/**
* 排序
*
* @param t
* @param map
* @return
*/
private <T> T addSort(T t, Map<String, String> map) {
String sortField = map.get("sortField");
String sortType = map.get("sortType");
Direction asc = Sort.Direction.DESC;
if ("ASC".equals(sortType)) {
asc = Sort.Direction.ASC;
}
if (t instanceof SimpleQuery) {
SimpleQuery query = (SimpleQuery) t;
Sort sort = new Sort(asc, "item_" + sortField);
query.addSort(sort);
}
if (t instanceof SimpleHighlightQuery) {
SimpleHighlightQuery query = (SimpleHighlightQuery) t;
Sort sort = new Sort(asc, "item_" + sortField);
query.addSort(sort);
}
return t;
}

/**
* 默认根据第一个模板ID查询品牌列表
*
* @param templateId
* @return
*/
private List searchBrandList(Long templateId) {
List<Map> brandList = (List<Map>) redisTemplate.boundHashOps("brandList").get(templateId);
return brandList;
}

/**
* 默认根据第一个模板ID查询规格选项列表
*
* @param templateId
* @return
*/
private List searchSpecList(Long templateId) {
List specList = (List) redisTemplate.boundHashOps("specList").get(templateId);
System.out.println(specList);
return specList;
}

}

文章目录