从零到壹搭建一个商城架构--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做反向代理的使用

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