完成搜尋模組功能,引入搜尋頁面。接收並封裝使用者的搜尋關鍵字、三級分類id、屬性值列表,對es執行查詢操作,並設定高亮!

Hiber12發表於2020-12-19

引入index首頁和list商品列表,兩個頁面。並且要對這些頁面進行路徑的修改,有點小bug

1、三級分類靜態資原始檔的載入路徑

在這裡插入圖片描述
修改路徑
在這裡插入圖片描述

2、修改list.gamll.com修改search.gmall.com:8083

在這裡插入圖片描述

3、三級分類的載入檔案的js,請求url改為search.gmall.com:8083

在這裡插入圖片描述

4、頁面引入之後,寫controller呼叫一下,看是否成功?

@Controller
public class SearchController {

    @RequestMapping("index")
    public void index(){
    }

    @RequestMapping("list")
    public void list(String keyword){

    }
}

Search.gmall.com下的首頁index和商品列表list正常呼叫
在這裡插入圖片描述
在這裡插入圖片描述

5、完成搜尋es資料庫功能

分析:
在首頁當中,可能使用者會搜尋關鍵字,也可能會點選三級分類id
在商品列表中,使用者還會多次點選商品的屬性值

那麼需要把這三個引數:關鍵字、三級分類id、屬性值列表,封裝成一個物件用來接收引數!

建立搜尋接收引數類PmsSearchParam,param是引數的翻譯

謹記要序列化對映類implements Serializable 英 [ˈɪmplɪments] 英[ˈsɪərɪəlaɪzəbl]

還有之前建立的PmsSearchSkuInfo類也要序列化,不然報錯

private String keyword;    //關鍵字
private String catalog3Id;  //三級分類id
private List<PmsSkuAttrValue> pmsSkuAttrValues;  //平臺屬性值列表

在controller類中list接收一個物件,成功接收到前端傳遞過來的引數:

@RequestMapping("list")
public void list(PmsSearchParam pmsSearchParam){

}

6、實體類做好了,就開始實現功能吧,查詢es:

@Service
public class SearchServiceImpl implements SearchService {

    @Autowired
    JestClient jestClient;

    @Override
    public List<PmsSearchSkuInfo> list(PmsSearchParam pmsSearchParam) {

        //呼叫生成dsl語句查詢es的方法,在下面
        String dslStr = dslStr(pmsSearchParam);

        //new一個查詢建立者物件
        Search search = new Search.Builder(dslStr).addIndex("gmall0105").addType("PmsSkuInfo").build();

        //jest客戶端execute處理那個物件,並得到一個查詢結果SearchResult
        SearchResult Result = null;
        try {
             Result = jestClient.execute(search);
        } catch (IOException e) {
            e.printStackTrace();
        }

        //查詢返回的結果,主要獲取它的hit匹配資料,有多少條,用泛型列表接收
        List<SearchResult.Hit<PmsSearchSkuInfo, Void>> hits = Result.getHits(PmsSearchSkuInfo.class);

        //把這個列表再遍歷,add進java對映類中的列表
        List<PmsSearchSkuInfo> pmsSearchSkuInfos = new ArrayList<>();
        for (SearchResult.Hit<PmsSearchSkuInfo, Void> hit : hits) {
            //使用對映類物件 接收每一個 hit匹配資料來源source
            PmsSearchSkuInfo source = hit.source;

            //使用map接收匹配資料的高亮
            Map<String, List<String>> highlight = hit.highlight;
            if(highlight!=null){
                //獲取高亮的欄位的資料
                String skuName = highlight.get("skuName").get(0);
                //用highlight處理過的欄位 替換掉 原來的skuName欄位
                source.setSkuName(skuName);
            }
            pmsSearchSkuInfos.add(source);
        }

        return pmsSearchSkuInfos;
    }

    private String dslStr(PmsSearchParam pmsSearchParam){

        String Catalog3Id = pmsSearchParam.getCatalog3Id();
        String Keyword = pmsSearchParam.getKeyword();
        String[] valueId = pmsSearchParam.getValueId();

        //new一個查詢資料來源物件
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        //new一個bool多重查詢條件物件,用來封裝你需要的查詢條件
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();

        //根據三級分類id查詢
        if(StringUtils.isNotBlank(Catalog3Id)) {
            TermQueryBuilder termQueryBuilder = new TermQueryBuilder("catalog3Id", Catalog3Id);
            boolQueryBuilder.filter(termQueryBuilder);
        }

        //根據關鍵字查詢
        if(StringUtils.isNotBlank(Keyword)){
            MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("skuName", Keyword);
            boolQueryBuilder.must(matchQueryBuilder);
        }

        //根據平臺屬性值查詢
        if(valueId!=null){
            for (String s : valueId) {
                TermQueryBuilder termQueryBuilder = new TermQueryBuilder("skuAttrValueList.valueId",s);
                boolQueryBuilder.filter(termQueryBuilder);
            }
        }

        //把這個bool物件丟進query方法中
        searchSourceBuilder.query(boolQueryBuilder);

        //查詢符合條件的30條資料
        searchSourceBuilder.from(0);
        searchSourceBuilder.size(30);

        //高亮,把關鍵字標紅
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<span style='color:red;'>");
        highlightBuilder.field("skuName");
        highlightBuilder.postTags("</span>");
        searchSourceBuilder.highlight(highlightBuilder);

        System.err.println(searchSourceBuilder.toString());

        return searchSourceBuilder.toString();
    }
}

7、設定高亮,根據關鍵字搜尋商品,搜尋出來的商品名稱的這個關鍵字變紅。

在es查詢到的結果返回到java後端,處理一下後端的skuName欄位,用高亮highlight處理過的欄位 替換掉 原來的skuName欄位,即skuName就會顯示高亮!!!

//把這個列表再遍歷,add進java對映類中的列表
List<PmsSearchSkuInfo> pmsSearchSkuInfos = new ArrayList<>();
for (SearchResult.Hit<PmsSearchSkuInfo, Void> hit : hits) {
    //使用對映類物件 接收每一個 hit匹配資料來源source
    PmsSearchSkuInfo source = hit.source;

    //使用map接收匹配資料的高亮
    Map<String, List<String>> highlight = hit.highlight;
    if(highlight!=null){
        //獲取高亮的欄位的資料
        String skuName = highlight.get("skuName").get(0);
        //用highlight的skuName欄位 替換掉 原來的skuName欄位
        source.setSkuName(skuName);
    }
    pmsSearchSkuInfos.add(source);
}

再使用樣式標籤,字首preTags和字尾postTags,讓這個關鍵字變紅。

//高亮,把關鍵字標紅
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.preTags("<span style='color:red;'>");
highlightBuilder.field("skuName");
highlightBuilder.postTags("</span>");
searchSourceBuilder.highlight(highlightBuilder);

8、在搜尋框輸入華為,測試成功:

在這裡插入圖片描述

相關文章