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