全文检索-Elasticsearch-整合SpringBoot

news/2024/11/7 20:59:36/

文章目录

  • 前言
  • 一、整合检索服务
    • 1.1 创建 gulimall-search 模块
    • 1.2 配置 Maven 依赖
    • 1.3 搜索服务注册到注册中心
    • 1.4 新增 es 配置类
    • 1.5 测试 RestHighLevelClient 组件
  • 二、存储数据到 ES
    • 2.1 测试 ES 简单插入数据
    • 2.2 测试 ES 查询复杂语句

前言

前面记录了 Elasticsearch 全文检索的入门篇和进阶检索。这次我们来讲下 Spring Boot 中如何整合 ES,以及如何在 Spring Cloud 微服务项目中使用 ES 来实现全文检索,来达到商品检索的功能。

一、整合检索服务

检索服务单独作为一个服务,就称作 gulimall-search 模块。

1.1 创建 gulimall-search 模块

在这里插入图片描述
点击 Next 勾选 Spring Web 依赖,点击 finish 即可

1.2 配置 Maven 依赖

1.添加 es 高阶客户端

<dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.4.2</version>
</dependency>

2.选择 java 和 elasticsearch 版本

<properties><java.version>1.8</java.version><elasticsearch.version>7.4.2</elasticsearch.version></properties>

3.将之前的 common 包导入

<dependency><groupId>com.atguigu.gulimall</groupId><artifactId>gulimall-common</artifactId><version>0.0.1-SNAPSHOT</version>
</dependency>

添加完依赖后,我们就可以将搜索服务注册到 nacos 注册中心了。 nacos 注册中心的用法在前面几篇文章中也详细讲解过,这里需要注意的是要先启动 nacos 注册中心,才能正常注册 gulimall-search 服务。

1.3 搜索服务注册到注册中心

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

给启动类添加服务发现注解:@EnableDiscoveryClient,这样 gulimall-search 服务就可以被注册中心发现了。

因 common 模块依赖数据源,但 search 模块不依赖数据源,所以该模块需要移除数据源依赖,检索服务启动类如下

@EnableDiscoveryClient
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class GulimallSearchApplication {public static void main(String[] args) {SpringApplication.run(GulimallSearchApplication.class, args);}}

1.4 新增 es 配置类

@Configuration
public class ElasticsearchConfig {@Bean// 给容器注册一个 RestHighLevelClient,用来操作 ES// 参考官方文档:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.9/java-rest-high-getting-started-initialization.htmlpublic RestHighLevelClient restHighLevelClient() {return new RestHighLevelClient(RestClient.builder(new HttpHost("192.168.57.129", 9200, "http")));}
}

1.5 测试 RestHighLevelClient 组件

@RunWith(SpringRunner.class)
@SpringBootTest
public class GulimallSearchApplicationTests {@Resourceprivate RestHighLevelClient restHighLevelClient;@Testpublic void contextLoads() {System.out.println(restHighLevelClient);}}

运行结果如下所示,打印出了 RestHighLevelClient。说明自定义的 ES Client 自动装载成功。

在这里插入图片描述

二、存储数据到 ES

2.1 测试 ES 简单插入数据

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();
}

测试类

/*** 测试存储数据到es* 更新也可以* @throws IOException*/
@Test
public void indexData() throws IOException {IndexRequest index = new IndexRequest("users");index.id("1");//第一种:index.source("userName","zhangsan","age","18","gender","男");//第二种:User user = new User();user.setUserName("zhangsan");user.setAge(18);user.setGender("男");String jsonString = JSON.toJSONString(user);//要保存的数据index.source(jsonString, XContentType.JSON);//执行操作IndexResponse response = restHighLevelClient.index(index, ElasticsearchConfig.COMMON_OPTIONS);//提取有用的响应数据System.out.println(response);
}@Data
class User{private String userName;private String gender;private Integer age;
}

控制台打印数据

在这里插入图片描述
测试数据存储到 es 成功

在这里插入图片描述

2.2 测试 ES 查询复杂语句

1.查看检索条件

@Test
public void searchData() throws IOException {// 1.创建检索请求SearchRequest request = new SearchRequest();// 指定索引request.indices("bank");// 指定DSL,检索条件// SearchSourceBuilder sourceBuilder 封装的条件SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();// 1.1构造检索条件
//        sourceBuilder.query();
//        sourceBuilder.from();
//        sourceBuilder.size();
//        sourceBuilder.aggregations();sourceBuilder.query(QueryBuilders.matchQuery("address", "mill"));System.out.println(sourceBuilder.toString());request.source(sourceBuilder);// 2.执行检索SearchResponse response = restHighLevelClient.search(request, ElasticsearchConfig.COMMON_OPTIONS);// 3.分析结果 responseSystem.out.println(response.toString());
}

查看检索结果

在这里插入图片描述
2.按照年龄值的分布和平均薪资进行聚合

@Test
public void searchData() throws IOException {// 1.创建检索请求SearchRequest request = new SearchRequest();// 指定索引request.indices("bank");// 指定DSL,检索条件// SearchSourceBuilder sourceBuilder 封装的条件SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();// 1.1构造检索条件
//        sourceBuilder.query();
//        sourceBuilder.from();
//        sourceBuilder.size();
//        sourceBuilder.aggregations();sourceBuilder.query(QueryBuilders.matchQuery("address","mill"));// 1.2按照年龄值的分布进行聚合TermsAggregationBuilder ageAgg = AggregationBuilders.terms("ageAgg").field("age").size(10);sourceBuilder.aggregation(ageAgg);// 1.3计算平均薪资AvgAggregationBuilder balance = AggregationBuilders.avg("balanceAvg").field("balance");sourceBuilder.aggregation(balance);System.out.println("检索条件:" + sourceBuilder.toString());request.source(sourceBuilder);// 2.执行检索SearchResponse response = restHighLevelClient.search(request, ElasticsearchConfig.COMMON_OPTIONS);// 3.分析结果 responseSystem.out.println(response.toString());
}

删除默认信息后,检索条件如下

{"query": {"match": {"address": {"query": "mill"}}},"aggregations": {"ageAgg": {"terms": {"field": "age","size": 10}},"balanceAvg": {"avg": {"field": "balance"}}}
}

复制检索条件到 Kibana 进行检索

在这里插入图片描述

整体测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class GulimallSearchApplicationTests {@Resourceprivate RestHighLevelClient restHighLevelClient;@Testpublic void searchData() throws IOException {// 1.创建检索请求SearchRequest request = new SearchRequest();// 指定索引request.indices("bank");// 指定DSL,检索条件// SearchSourceBuilder sourceBuilder 封装的条件SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();// 1.1构造检索条件
//        sourceBuilder.query();
//        sourceBuilder.from();
//        sourceBuilder.size();
//        sourceBuilder.aggregations();sourceBuilder.query(QueryBuilders.matchQuery("address","mill"));// 1.2按照年龄值的分布进行聚合TermsAggregationBuilder ageAgg = AggregationBuilders.terms("ageAgg").field("age").size(10);sourceBuilder.aggregation(ageAgg);// 1.3计算平均薪资AvgAggregationBuilder balance = AggregationBuilders.avg("balanceAvg").field("balance");sourceBuilder.aggregation(balance);System.out.println("检索条件:" + sourceBuilder.toString());request.source(sourceBuilder);// 2.执行检索SearchResponse response = restHighLevelClient.search(request, ElasticsearchConfig.COMMON_OPTIONS);// 3.分析结果 responseSystem.out.println(response.toString());// Map map = JSON.parseObject(searchResponse.toString(), Map.class);//3.1)、获取所有查到的数据SearchHits hits = response.getHits();SearchHit[] searchHits = hits.getHits();for (SearchHit hit : searchHits) {/*** "_index" : "bank",*         "_type" : "account",*         "_id" : "970",*         "_score" : 5.4598455,*         "_source" : {*/
//            hit.getIndex();hit.getType();hit.getId();String string = hit.getSourceAsString();Account account = JSON.parseObject(string, Account.class);System.out.println("account: " + account);}//3.2)、获取这次检索到的分析信息;Aggregations aggregations = response.getAggregations();
//        for (Aggregation aggregation : aggregations.asList()) {
//            System.out.println("当前聚合:"+aggregation.getName());
//            aggregation.getName()
//        }Terms ageAgg1 = aggregations.get("ageAgg");for (Terms.Bucket bucket : ageAgg1.getBuckets()) {String keyAsString = bucket.getKeyAsString();System.out.println("年龄:"+keyAsString+"==>"+bucket.getDocCount());}Avg balanceAvg1 = aggregations.get("balanceAvg");System.out.println("平均薪资:"+balanceAvg1.getValue());}/*** 测试存储数据到es* 更新也可以* @throws IOException*/@Testpublic void indexData() throws IOException {IndexRequest index = new IndexRequest("users");index.id("1");//第一种:index.source("userName","zhangsan","age","18","gender","男");//第二种:User user = new User();user.setUserName("zhangsan");user.setAge(18);user.setGender("男");String jsonString = JSON.toJSONString(user);//要保存的数据index.source(jsonString, XContentType.JSON);//执行操作IndexResponse response = restHighLevelClient.index(index, ElasticsearchConfig.COMMON_OPTIONS);//提取有用的响应数据System.out.println(response);}@Testpublic void contextLoads() {System.out.println(restHighLevelClient);}@Dataclass User{private String userName;private String gender;private Integer age;}@Data@ToStringstatic class Account {private int account_number;private int balance;private String firstname;private String lastname;private int age;private String gender;private String address;private String employer;private String email;private String city;private String state;}
}

控制台输出

检索条件:{"query":{"match":{"address":{"query":"mill","operator":"OR","prefix_length":0,"max_expansions":50,"fuzzy_transpositions":true,"lenient":false,"zero_terms_query":"NONE","auto_generate_synonyms_phrase_query":true,"boost":1.0}}},"aggregations":{"ageAgg":{"terms":{"field":"age","size":10,"min_doc_count":1,"shard_min_doc_count":0,"show_term_doc_count_error":false,"order":[{"_count":"desc"},{"_key":"asc"}]}},"balanceAvg":{"avg":{"field":"balance"}}}}
{"took":1,"timed_out":false,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0},"hits":{"total":{"value":4,"relation":"eq"},"max_score":5.4598455,"hits":[{"_index":"bank","_type":"account","_id":"970","_score":5.4598455,"_source":{"account_number":970,"balance":19648,"firstname":"Forbes","lastname":"Wallace","age":28,"gender":"M","address":"990 Mill Road","employer":"Pheast","email":"forbeswallace@pheast.com","city":"Lopezo","state":"AK"}},{"_index":"bank","_type":"account","_id":"136","_score":5.4598455,"_source":{"account_number":136,"balance":45801,"firstname":"Winnie","lastname":"Holland","age":38,"gender":"M","address":"198 Mill Lane","employer":"Neteria","email":"winnieholland@neteria.com","city":"Urie","state":"IL"}},{"_index":"bank","_type":"account","_id":"345","_score":5.4598455,"_source":{"account_number":345,"balance":9812,"firstname":"Parker","lastname":"Hines","age":38,"gender":"M","address":"715 Mill Avenue","employer":"Baluba","email":"parkerhines@baluba.com","city":"Blackgum","state":"KY"}},{"_index":"bank","_type":"account","_id":"472","_score":5.4598455,"_source":{"account_number":472,"balance":25571,"firstname":"Lee","lastname":"Long","age":32,"gender":"F","address":"288 Mill Street","employer":"Comverges","email":"leelong@comverges.com","city":"Movico","state":"MT"}}]},"aggregations":{"lterms#ageAgg":{"doc_count_error_upper_bound":0,"sum_other_doc_count":0,"buckets":[{"key":38,"doc_count":2},{"key":28,"doc_count":1},{"key":32,"doc_count":1}]},"avg#balanceAvg":{"value":25208.0}}}
account: GulimallSearchApplicationTests.Account(account_number=970, balance=19648, firstname=Forbes, lastname=Wallace, age=28, gender=M, address=990 Mill Road, employer=Pheast, email=forbeswallace@pheast.com, city=Lopezo, state=AK)
account: GulimallSearchApplicationTests.Account(account_number=136, balance=45801, firstname=Winnie, lastname=Holland, age=38, gender=M, address=198 Mill Lane, employer=Neteria, email=winnieholland@neteria.com, city=Urie, state=IL)
account: GulimallSearchApplicationTests.Account(account_number=345, balance=9812, firstname=Parker, lastname=Hines, age=38, gender=M, address=715 Mill Avenue, employer=Baluba, email=parkerhines@baluba.com, city=Blackgum, state=KY)
account: GulimallSearchApplicationTests.Account(account_number=472, balance=25571, firstname=Lee, lastname=Long, age=32, gender=F, address=288 Mill Street, employer=Comverges, email=leelong@comverges.com, city=Movico, state=MT)
年龄:38==>2
年龄:28==>1
年龄:32==>1
平均薪资:25208.0
2023-05-12 22:43:00.325  INFO 17832 --- [       Thread-9] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'Process finished with exit code 0

http://www.ppmy.cn/news/67982.html

相关文章

java版spring cloud 企业电子招投标采购系统源码之首页设计

随着公司的快速发展&#xff0c;企业人员和经营规模不断壮大&#xff0c;公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境&#xff0c;最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范&#xff0c;以及审计监督要…

vue 组件 隐藏内容,点击展示更多功能

效果图 代码 <template><div class"m-text-overflow modules"><div class"l-content" :style"contentStyle"><div ref"refContent"><slot><span v-html"content"> </span></…

泛型(Generic) 类型擦除

什么是类型擦除 泛型是 Java 1.5 版本才引进的概念&#xff0c;在这之前是没有泛型的概念的&#xff0c;但是泛型代码能够很好地和之前版本的代码很好地兼容。这是因为&#xff0c;泛型信息只存在于代码编译阶段&#xff0c;在进入 JVM 之前&#xff0c;与泛型相关的信息会被擦…

算法修炼之练气篇——练气二层

博主&#xff1a;命运之光 专栏&#xff1a;算法修炼之练气篇 前言&#xff1a;每天练习五道题&#xff0c;炼气篇大概会练习200道题左右&#xff0c;题目有C语言网上的题&#xff0c;也有洛谷上面的题&#xff0c;题目简单适合新手入门。&#xff08;代码都是命运之光自己写的…

电商如何利用API接口获取商品信息数据

随着电商和互联网的快速发展&#xff0c;API&#xff08;应用程序编程接口&#xff09;的重要性也越来越明显。API接口可以让不同系统之间进行数据交互和通信&#xff0c;进而实现更高效的业务协同和数据共享。在电商业务中&#xff0c;API可以帮助企业实现多个业务系统之间的数…

由浅入深理解java集合(三)——集合 List

一、List集合 List集合判断元素相等的标准 List判断两个对象相等只要通过equals()方法比较返回true即可&#xff08;关于equals()方法的详解可以参考第二篇文章中的内容&#xff09;。 下面以用代码具体展示。 创建一个Book类&#xff0c;并重写equals()方法&#xff0c;如果两…

FISCO BCOS(三十五)———Python Sdk linux 环境控制台使用

注:按照之前的一键部署所有流程先走完,再做以下操作,注意我们的操作全部在ubuntu上进行,不考虑其他环境(我把坑踩完了,按照我的来不会采坑) pythonsdk Gitee地址:https://gitee.com/wei_hong_liang/python-sdk?_from=gitee_search#python-sdk1、安装python-sdk依赖软件 …

sorna python3 调用,python 获取sonarqube数据

1.sonarqube是一款代码分析的工具&#xff0c;通过soanrScanner扫描后的数据传递给sonarqube进行分析 2.sonarqube社区版没有对c类代码的分析&#xff0c;但是可以找到一个开源的包&#xff0c;安装即可&#xff0c;扫描的话可以使用cppcheck来进行扫描 安装python对于sonarqu…