從零到壹搭建一個商城架構--ElasticSearch-Rest-Client

ElasticSearch-Rest-Client 是官方RestClient,封裝了ES操作,API層次分明,上手簡單

我們選擇ElasticSearch-Rest-Client(elasticsearch-rest-high-level-client)

按照官方文檔,先安裝依賴,在進行配置

https://www.elastic.co/guide/en/elasticsearch/client/index.html

1、創建一個springboot工程,hslmall_search,在pom文件中加入如下依賴

<!--引入公共依賴-->
<dependency>
    <groupId>com.hsl.halmall</groupId>
    <artifactId>hslmall-common</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>
<!--引入ES依賴-->
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>7.4.2</version>
</dependency>

然後我們在加入以下配置,來進行版本的統一

<!--定義ES版本號-->
<properties>
    <elasticsearch.version>7.4.2</elasticsearch.version>
</properties>

2、添加配置文件

@Configuration
public class ElasticSearchConfig {

    public static final RequestOptions COMMON_OPTIONS;
    static {
        RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
//        builder.addHeader("Authorization", "Bearer " + TOKEN);
//        builder.setHttpAsyncResponseConsumerFactory(
//                new HttpAsyncResponseConsumerFactory
//                        .HeapBufferedResponseConsumerFactory(30 * 1024 * 1024 * 1024));
        COMMON_OPTIONS = builder.build();
    }

    @Bean
    public RestHighLevelClient esRestClient(){
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost("192.168.56.10", 9200, "http")));
        return client;
    }
}

3、把搜索服務註冊到註冊中心

spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
spring.application.name=hslmall-search

4、主配置類加註解

//啓用註冊中心配置
@EnableDiscoveryClient
//排除操作數據庫依賴
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class HslmallSearchApplication {

    public static void main(String[] args) {
        SpringApplication.run(HslmallSearchApplication.class, args);
    }
}

5、測試搜索服務配置是否可用

@SpringBootTest
class HslmallSearchApplicationTests {

    @Autowired
    private RestHighLevelClient client;

    //索引數據
    @Test
    void indexData() throws IOException {
        //創建索引users
        IndexRequest indexRequest=new IndexRequest("users");
        //設置索引id爲1
        indexRequest.id("1");

        User user=new User();
        user.setUserName("張三");
        user.setAge(18);
        user.setGender("男");
        String jsonString = JSON.toJSONString(user);
        //把數據給索引傳遞
        IndexRequest request = indexRequest.source(jsonString, XContentType.JSON);
        //發送保存操作
        IndexResponse index = client.index(request, ElasticSearchConfig.COMMON_OPTIONS);
        System.out.println(index);
    }

    @Data
    class User{
        private String userName;
        private Integer age;
        private String gender;
    }
    
    //搜索數據
    @Test
    void searchData() throws IOException {
        //創建檢索請求
        SearchRequest searchRequest = new SearchRequest();
        //指定DSL檢索條件
        searchRequest.indices("bank");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.matchQuery("address", "mill"));
        //按照年齡值進行聚合
        TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("ageAgg").field("age").size(10);
        sourceBuilder.aggregation(termsAggregationBuilder);
        //計算平均薪資
        AvgAggregationBuilder avgAggregationBuilder = AggregationBuilders.avg("balenceAavg").field("balance");
        sourceBuilder.aggregation(avgAggregationBuilder);
        System.out.println("檢索條件:" + sourceBuilder);
        searchRequest.source(sourceBuilder);
        //執行檢索
        SearchResponse searchResponse = client.search(searchRequest, ElasticSearchConfig.COMMON_OPTIONS);
        //分析結果
        System.out.println("返回結果" + searchResponse);
        //獲取返回的數據
        SearchHits hits = searchResponse.getHits();
        SearchHit[] hitsHits = hits.getHits();
        for (SearchHit hit : hitsHits) {
            String sourceAsString = hit.getSourceAsString();
            System.out.println(sourceAsString);
        }
        //獲取聚合信息
        Aggregations aggregations = searchResponse.getAggregations();
        Terms ageAgg = aggregations.get("ageAgg");
        for (Terms.Bucket bucket : ageAgg.getBuckets()) {
            String keyAsString = bucket.getKeyAsString();
            System.out.println("年齡分佈:"+keyAsString);
        }
        Avg aavg = aggregations.get("balenceAavg");
        double aavgValue = aavg.getValue();
        System.out.println("平均薪資:"+aavgValue);
    }

}

6、把sku信息保存在es中

在kibana控制檯執行以下代碼,用於保存快速檢索商品信息的屬性配置,這就相當於是創建mysql的表結構一樣

PUT product
{
  "mappings": {
    "properties": {
      "skuId": {
        "type": "long"
      },
      "spuId": {
        "type": "keyword"
      },
      "skuTitle": {
        "type": "text",
        "analyzer": "ik_smart"
      },
      "skuPrice": {
        "type": "keyword"
      },
      "skuImg": {
        "type": "keyword",
        "index": false,
        "doc_values": false
      },
      "saleCount": {
        "type": "long"
      },
      "hasScore": {
        "type": "boolean"
      },
      "hotScore": {
        "type": "long"
      },
      "brandId": {
        "type": "long"
      },
      "catelogId": {
        "type": "long"
      },
      "brandName": {
        "type": "keyword",
        "index": false,
        "doc_values": false
      },
      "brandImg": {
        "type": "keyword",
        "index": false,
        "doc_values": false
      },
      "catelogName": {
        "type": "keyword",
        "index": false,
        "doc_values": false
      },
      "attrs": {
        "type": "nested",
        "properties": {
          "attrId": {
            "type": "long"
          },
          "attrName": {
            "type": "keyword",
            "index": false,
            "doc_values":false
          },
          "attrValue": {
            "type": "keyword"
          }
        }
      }
    }
  }
}

7、把數據庫中的數據保存到ES中

    public boolean productUp(List<SkuEsModel> skuEsModels) throws IOException {

        //給ES中建立一個索引,創建好映射關係

        if(skuEsModels!=null&&skuEsModels.size()>0){
            //把數據保存到ES中,BulkRequest是批量保存
            BulkRequest bulkRequest = new BulkRequest();
            for (SkuEsModel model:skuEsModels){
                IndexRequest indexRequest = new IndexRequest(ESConstnt.PRODUCT_INDEX);
                indexRequest.id(model.getSkuId().toString());
                String jsonString = JSON.toJSONString(model);
                indexRequest.source(jsonString, XContentType.JSON);
                bulkRequest.add(indexRequest);
            }
            BulkResponse bulk = client.bulk(bulkRequest, ElasticSearchConfig.COMMON_OPTIONS);
            boolean failures = bulk.hasFailures();
            List<String> collect =new ArrayList<>();
            if(failures){
                collect = Arrays.stream(bulk.getItems()).map(item -> item.getId()).collect(Collectors.toList());
                log.error("商品上架到ES中出現錯誤,{}",collect);
            }else{
                log.info("商品上架到ES中完成",collect);
            }
            return failures;
        }
        return false;
    }

我們在頁面點擊上架後,會遠程調用上面這段代碼,這樣就把我們數據庫中提取出來的數據保存到ES中了

在kibana中執行GET product/_search會看到如下內容

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "product",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 1.0,
        "_source" : {
          "attrs" : [
            {
              "attrId" : 6,
              "attrName" : "入網型號",
              "attrValue" : "VOG-AL00"
            },
            {
              "attrId" : 9,
              "attrName" : "上市月份",
              "attrValue" : "1月"
            },
            {
              "attrId" : 10,
              "attrName" : "機身顏色",
              "attrValue" : "極光色"
            },
            {
              "attrId" : 11,
              "attrName" : "機身長度(mm)",
              "attrValue" : "158"
            },
            {
              "attrId" : 12,
              "attrName" : "機身重量(g)",
              "attrValue" : "192"
            },
            {
              "attrId" : 13,
              "attrName" : "機身材質工藝",
              "attrValue" : "以官網信息爲準"
            },
            {
              "attrId" : 14,
              "attrName" : "CPU品牌",
              "attrValue" : "海思(Hisilicon)"
            },
            {
              "attrId" : 15,
              "attrName" : "CPU型號",
              "attrValue" : "麒麟980"
            },
            {
              "attrId" : 16,
              "attrName" : "存儲卡",
              "attrValue" : "NM存儲卡"
            },
            {
              "attrId" : 17,
              "attrName" : "運行內存",
              "attrValue" : "8GB"
            },
            {
              "attrId" : 18,
              "attrName" : "分辨率",
              "attrValue" : "FHD+ 2340*1080 像素"
            },
            {
              "attrId" : 19,
              "attrName" : "屏幕像素密度(ppi)",
              "attrValue" : "398 PPI"
            },
            {
              "attrId" : 22,
              "attrName" : "前攝的主攝像素",
              "attrValue" : "3200萬像素"
            },
            {
              "attrId" : 23,
              "attrName" : "電池是否可拆卸",
              "attrValue" : "電池不可拆卸"
            },
            {
              "attrId" : 24,
              "attrName" : "充電器",
              "attrValue" : "10V/4A"
            },
            {
              "attrId" : 25,
              "attrName" : "操作系統",
              "attrValue" : "Android(安卓)"
            },
            {
              "attrId" : 26,
              "attrName" : "雙卡機類型",
              "attrValue" : "雙卡雙待"
            },
            {
              "attrId" : 27,
              "attrName" : "數據傳輸接口",
              "attrValue" : "WIFI;NFC"
            },
            {
              "attrId" : 29,
              "attrName" : "常用功能",
              "attrValue" : "錄音;手勢識別"
            }
          ],
          "brandId" : 1,
          "brandImg" : "https://hslmall.oss-cn-beijing.aliyuncs.com/2020-04-24/2d1aded2-75b5-4b6e-87d0-bc00858a5901_Mysnapshot.jpg",
          "brandName" : "華爲",
          "catelogName" : "手機",
          "hasScore" : true,
          "hotScore" : 0,
          "saleCount" : 0,
          "skuId" : 3,
          "skuImg" : "https://hslmall.oss-cn-beijing.aliyuncs.com/2020-04-30//2c357c9f-640b-4c24-8a2e-0ac873ed6b07_亮黑色-圖集1.jpg",
          "skuPrice" : 4000.0,
          "skuTitle" : "華爲111 天空之境  8GB+128GB",
          "spuId" : 9
        }
      }
    ]
  }
}

說明我們就把數據庫中的數據保存到了ES中了,這樣後面我們在使用模糊檢索的時候,查詢速度會很快的展示
下面我們在說一說使用nginx做反向代理的使用

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章