ElasticSearch-Rest-Client 是官方RestClient,封装了ES操作,API层次分明,上手简单
我们选择ElasticSearch-Rest-Client(elasticsearch-rest-high-level-client)
按照官方文档,先安装依赖,在进行配置
https://www.elastic.co/guide/en/elasticsearch/client/index.html
<dependency>
<groupId>com.hsl.halmallgroupId>
<artifactId>hslmall-commonartifactId>
<version>0.0.1-SNAPSHOTversion>
dependency>
<dependency>
<groupId>org.elasticsearch.clientgroupId>
<artifactId>elasticsearch-rest-high-level-clientartifactId>
<version>7.4.2version>
dependency>
然后我们在加入以下配置,来进行版本的统一
<properties>
<elasticsearch.version>7.4.2elasticsearch.version>
properties>
@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;
}
}
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
spring.application.name=hslmall-search
//启用注册中心配置
@EnableDiscoveryClient
//排除操作数据库依赖
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class HslmallSearchApplication {
public static void main(String[] args) {
SpringApplication.run(HslmallSearchApplication.class, args);
}
}
@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);
}
}
在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"
}
}
}
}
}
}
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做反向代理的使用