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做反向代理的使用