Elasticsearch簡單的使用步驟以及查詢模塊的實現


1)搭建ES服務器(單機、集群)
2)創建映射,建立實體和索引庫的映射關系,使用spring-data-elasticsearch
  //ES提供的接口,可以對索引庫進行CRUD操作;T建立了和索引庫映射關系的對象、ID為T對象中的主鍵類型
  ElasticsearchRepository<T,ID>

  //操作索引庫
  ElasticSearchTemplate
3)索引庫維護(初始化數據導入全量索引、增量索引、索引同步、定時索引(全量索引、增量索引),手動索引)

 

ES支持的搜索功能:

分頁查詢、精確查詢、范圍查詢、排序、分頁、高亮、分組、正則、模糊、前后綴、一值多域、一域多值

 

 

RestHighLevelClient實現搜索

  

//RestHighLevelClient實現搜索功能
//3個重要查詢對象SearchRequest、SearchSourceBuilder(排序、分頁、高亮、分組)、BoolQueryBuilder
@Autowired
private RestHighLevelClient restHighLevelClient;//准備工作,注入RestHighLevelClient
public Map search(Map<String,String> searchMap) {
    //1.封裝查詢請求,指定“索引庫”,“類型”
    SearchRequest searchRequest=new SearchRequest("sku");
    searchRequest.types("doc"); //設置查詢的類型
    SearchSourceBuilder searchSourceBuilder=new SearchSourceBuilder();
    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();//布爾查詢構建器
    //1.1 關鍵字搜索
    if (StringUtils.isNotEmpty(searchMap.get("keywords"))){
        boolQueryBuilder.must(QueryBuilders.matchQuery("name",searchMap.get("keywords"));
    }
    //1.2 靜態過濾,key固定
    if(searchMap.get("category")!=null){
        boolQueryBuilder.filter(QueryBuilders.termQuery("categoryName", searchMap.get("category"));
    }
    //1.4 動態過濾,key是拼接后得到
    for(String key: searchMap.keySet() ){
        if( key.startsWith("spec.") ){//如果是規格參數
            TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(key+".keyword", searchMap.get(key));
            boolQueryBuilder.filter(termQueryBuilder);
        }
    }
    //1.5 數值區間過濾
    if(searchMap.get("price")!=null ){
        String[] price = searchMap.get("price").split("-");
        if (prices.length == 2){
             boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").lte(prices[1]));
        }
        boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(prices[0]));
    }
    searchSourceBuilder.query(boolQueryBuilder);
    //分頁
    searchSourceBuilder.from(fromIndex);//開始索引設置
    searchSourceBuilder.size(pageSize);//每頁記錄數設置
    //排序 
    searchSourceBuilder.sort("排序的域", "順序DESC|ASC");
    //高亮設置
    HighlightBuilder highlightBuilder=new HighlightBuilder();
    highlightBuilder.field("name").preTags("<font style='color:red'>").postTags("</font>");
    searchSourceBuilder.highlighter(highlightBuilder);
    searchRequest.source(searchSourceBuilder);
    //聚合查詢(商品分類)
    TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("sku_category").field("categoryName");
    searchSourceBuilder.aggregation(termsAggregationBuilder);
    //2.封裝查詢結果
    Map resultMap=new HashMap();
    try {
        SearchResponse searchResponse  = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits searchHits = searchResponse.getHits();
        long totalHits = searchHits.getTotalHits();
        System.out.println("記錄數:"+totalHits);
        SearchHit[] hits = searchHits.getHits();
​
        //2.1 商品列表
        List<Map<String,Object>> resultList=new ArrayList<Map<String, Object>>();
        for(SearchHit hit:hits){
            Map<String, Object> skuMap = hit.getSourceAsMap();
            //name高亮處理
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            HighlightField name = highlightFields.get("name");
            Text[] fragments = name.fragments();
            skuMap.put("name",fragments[0].toString());//用高亮的內容替換原內容
            resultList.add(skuMap);
        }
        resultMap.put("rows",resultList);
        //2.2 商品分類列表
        Aggregations aggregations = searchResponse.getAggregations();
        Map<String, Aggregation> aggregationMap = aggregations.getAsMap();
        Terms terms = (Terms) aggregationMap.get("sku_category");
        List<? extends Terms.Bucket> buckets =  terms.getBuckets();
        List<String> categoryList=new ArrayList();
        for( Terms.Bucket bucket:buckets ){
            categoryList.add(bucket.getKeyAsString());
    }
resultMap.put("categoryList",categoryList);
String categoryName = "";//商品分類名稱
if (searchMap.get("category") == null) { // 如果沒有分類條件
if (categoryList.size() > 0) {
categoryName = categoryList.get(0);//提取分類列表的第一個分類
    }
    } else {
categoryName = searchMap.get("category");//取出參數中的分類
    }
//2.3 品牌列表
if(searchMap.get("brand")==null) {
List<Map> brandList = brandMapper.findListByCategoryName(categoryName);//查詢品牌列表
resultMap.put("brandList", brandList);
    }
​
//2.4 規格列表
List<Map> specList = specMapper.findListByCategoryName(categoryName);//規格列表
for(Map spec:specList){
String[] options = ((String) spec.get("options")).split(",");//規格選項列表
spec.put("options",options);
    }
resultMap.put("specList",specList);
​
//2.5 頁碼
long totalCount = searchHits.getTotalHits();  //總記錄數
long pageCount = (totalCount%pageSize==0 )?totalCount/pageSize:(totalCount/pageSize+1);//總頁數
resultMap.put("totalPages",pageCount);
​
    } catch (IOException e) {
e.printStackTrace();
    }
return resultMap;
}

 

ElasticsearchTemplate實現搜索

//ElasticsearchTemplate(Sring-data-ElasticSearch)實現搜索功能
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;//准備工作,注入ElasticsearchTemplate
//(1)構建搜索條件對象NativeSearchQueryBuilder:SearchRequest+SearchSourceBuilder
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
//(2)構建多條件拼接查詢對象BoolQueryBuilder
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
//(3)往多條件拼接條件對象BoolQueryBuilder中添加條件
//boolQuery.must|should|mustNot|filter(QueryBuilders.xxxx)
        //xxxx表示查詢類型,例如:term、match、range(正則、模糊、前后綴)
...????...//其它條件省略
//(4)多條件查詢對象BoolQueryBuilder,放入整理查詢對象中
nativeSearchQueryBuilder.withQuery(boolQuery);
//(5)使用NativeSearchQueryBuilder設置分組、分頁、排序、高亮查詢條件
//nativeSearchQueryBuilder.addAggregation|withPageable|withSort|withHighlightFields
...????...
//(6)獲取查詢結果“頁面展示數據結果集--->‘高亮結果集’”、“搜索面板條件數據”、“分頁數據”
AggregatedPage<SkuInfo> resultInfo = elasticsearchTemplate.queryForPage(nativeSearchQueryBuilder.build(), SkuInfo.class, new SearchResultMapper() {
    @Override
    public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) {
        //1.查詢“頁面展示數據結果集--->‘高亮結果集’”
        List<T> list = new ArrayList<>();
        //獲取查詢命中結果數據
        SearchHits hits = searchResponse.getHits();
        if (hits != null){
            //有查詢結果
            for (SearchHit hit : hits) {
                //SearchHit轉換為skuinfo
                SkuInfo skuInfo = JSON.parseObject(hit.getSourceAsString(), SkuInfo.class);
                //獲取高亮數據,封裝到”頁面展示數據結果集“中
                Map<String, HighlightField> highlightFields = hit.getHighlightFields();
                if (highlightFields != null && highlightFields.size()>0){
                    //替換數據
                    skuInfo.setName(highlightFields.get("name").getFragments()[0].toString());
                }
                list.add((T) skuInfo);
            }
        }
        return new AggregatedPageImpl<T>(list,pageable,hits.getTotalHits(),searchResponse.getAggregations());
    }
});
//2.“搜索面板條件數據”,分組查詢結果
//封裝品牌的分組結果
StringTerms brandTerms = (StringTerms) resultInfo.getAggregation(skuBrand);
List<String> brandList = brandTerms.getBuckets().stream().map(bucket -> bucket.getKeyAsString()).collect(Collectors.toList());
//封裝規格分組結果
StringTerms specTerms= (StringTerms) resultInfo.getAggregation(skuSpec);
List<String> specList = specTerms.getBuckets().stream().map(bucket -> bucket.getKeyAsString()).collect(Collectors.toList());
//3.“分頁數據”
long total = resultInfo.getTotalElements();//總條數
int totalPages = resultInfo.getTotalPages()//總頁數
//4.查詢結果封裝
Map<String,Object> resultMap = new HashMap<>();
//總記錄數
resultMap.put("total",resultInfo.getTotalElements());
//總頁數
resultMap.put("totalPages",resultInfo.getTotalPages());
//數據集合
resultMap.put("rows",resultInfo.getContent());
//搜索面板-品牌列表
resultMap.put("brandList",brandList);
//搜索面板-規格列表
resultMap.put("specList",this.formartSpec(specList));
//搜索條件數據回顯(定義在controller層進行返回)

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM