1. 程式人生 > 實用技巧 >使用 elasticsearch 進行 搜尋熱門詞彙的展示很排序

使用 elasticsearch 進行 搜尋熱門詞彙的展示很排序

產品需求: 統計app 使用者輸入搜尋框的熱門詞彙,找出前十個排列展示;使用者點選對應詞彙,繼續跳轉搜尋頁面;

實現方式有很多種,歡迎大家指出問題;

我用的是Elasticsearch 來進行熱門詞彙的儲存和統計;

首先,使用者每次在搜尋框中搜索東西,我都會將輸入的內容儲存到es 中單獨一個index,用來儲存資訊;

儲存的結構資訊可以很簡單,如下內容 :

輸入詞的內容;

下次點選搜尋進行的埋點處理這裡可以是內容也可以是指定搜尋的內容;

以及每條記錄的id值;

可以有時間戳資訊;

這裡是java API 程式碼
public ResultPoJo addIndexSearchOtherThye(HotKeyWordsPo hotKeyWordsPo) { ResultPoJo
<?> poJo = new ResultPoJo<>(ConstantError.NOMAL); // 組裝搜尋詞 HotKeyWordsSearchPojo hotKeyWordsSearchPojo = new HotKeyWordsSearchPojo(); hotKeyWordsSearchPojo.setSearchInput(hotKeyWordsPo.getSearchInput()); hotKeyWordsSearchPojo.setId(ConverterUtil.getUUID()); hotKeyWordsSearchPojo.setCreateDate(OffsetDateTimeUtils.getDateNow().toEpochSecond());
// 插入到索引庫資料 if (ConverterUtil.isNotEmpty(hotKeyWordsSearchPojo)) { elasticsearchRestHighLevelClient.index("search-hotkey", SearchType.HotKeyWords.toString(), ConverterUtil.toString(hotKeyWordsSearchPojo.getId()), hotKeyWordsSearchPojo); } return poJo; }

將搜尋詞儲存進去以後,就是對索引內容的搜尋了:

/**
     * 熱搜列表搜尋
     *
     * @param pojo
     * @return
     * @throws JsonProcessingException
     */
    public ResultPoJo<Map<String, Object>> restSearchHotWords(CommditySearchPojo pojo) throws JsonProcessingException {

        ResultPoJo<Map<String, Object>> resultPoJo = new ResultPoJo(ConstantCodeMsg.NOMAL);
        int start = (pojo.getPageNo() - 1) * pojo.getPageSize();
        String s = "searchInput";
        String index = "search-hotkey";
       
        // 根據指定欄位進行分組,對應的docCount就是 文件中出現的次數
        TermsAggregationBuilder teamAgg = AggregationBuilders.terms("hotWords_count").field(s.concat(".").concat("keyword"));
        teamAgg.order(BucketOrder.count(true));
        SearchResponse searchResp;
        SearchResponse allResp;
        try {
            SearchRequest searchRequest = new SearchRequest(index);
            searchRequest.types(SearchType.HotKeyWords.toString());
            searchRequest.searchType(org.elasticsearch.action.search.SearchType.DFS_QUERY_THEN_FETCH);
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            sourceBuilder.query(bqb);
            searchRequest.source(sourceBuilder);
            allResp = elasticsearchRestHighLevelClient.client.search(searchRequest, COMMON_OPTIONS);

            SearchRequest searchRequests = new SearchRequest(index);
            searchRequests.types(SearchType.HotKeyWords.toString());
            searchRequests.searchType(org.elasticsearch.action.search.SearchType.DFS_QUERY_THEN_FETCH);
            SearchSourceBuilder sourceBuilders = new SearchSourceBuilder();

            sourceBuilders.aggregation(teamAgg);
            sourceBuilders.from(start);
            sourceBuilders.size(pojo.getPageSize());
            sourceBuilders.explain(true);
            sourceBuilders.query(bqb);
            searchRequests.source(sourceBuilders);
            searchResp = elasticsearchRestHighLevelClient.client.search(searchRequests, COMMON_OPTIONS);
        } catch (Exception e) {
            System.out.println(e);
            Map<String, Object> stringObjectMap = elasticsearchRestHighLevelClient.responseToJson(pojo.getPageNo(), pojo.getPageSize());
            resultPoJo.setResult(stringObjectMap);
            return resultPoJo;
        }
        Map<String, Object> stringObjectMap = elasticsearchRestHighLevelClient.responseToJsonHotKey(searchResp, allResp, pojo.getPageNo(), pojo.getPageSize());
        resultPoJo.setResult(stringObjectMap);
        return resultPoJo;
    }
hotWords_count 即對應index 中 輸入詞的內容資訊;
/**
     * 序列化查詢結果,包含分頁資訊
     *
     * @param searchResponse 當前頁的查詢結果
     * @param allResponse    所有滿足條件的查詢結果
     * @param pageNo         當前頁
     * @param pageSize       頁面大小
     * @return
     * @throws JsonProcessingException
     */
    public Map<String, Object> responseToJsonHotKey(SearchResponse searchResponse, SearchResponse allResponse, int pageNo, int pageSize) throws JsonProcessingException {
        Map<String, Object> jsonMap = new HashMap<String, Object>();
        // 總資料條數
        long count = allResponse.getHits().getTotalHits();

        Map<String, Aggregation> asMap = searchResponse.getAggregations().getAsMap();
        ParsedStringTerms hotWordsCount = (ParsedStringTerms) asMap.get("hotWords_count");
        List<? extends Terms.Bucket> buckets = hotWordsCount.getBuckets();
        long totalCount = buckets.size();
        // 總頁數
        int totalPageNum = ((int) count + pageSize - 1) / pageSize;
        Map<String, Object> pageMap = new HashMap<String, Object>();
        pageMap.put("pageNo", pageNo);
        pageMap.put("pageSize", pageSize);
        pageMap.put("count", count);
        pageMap.put("totalPageNum", totalPageNum);
        pageMap.put("totalCount", totalCount);
        jsonMap.put("page", pageMap);
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        for (Terms.Bucket bucket : buckets) {
            Map<String, Object> listMap = new HashMap<String, Object>();
            listMap.put("count", bucket.getDocCount());
            listMap.put("hotWordsName", bucket.getKeyAsString());
            list.add(listMap);
        }
        jsonMap.put("list", list);
        return jsonMap;
    }
根據指定欄位進行分組,對應的docCount就是 文件中出現的次數;