全文检索-Elasticsearch-整合SpringBoot

这篇具有很好参考价值的文章主要介绍了全文检索-Elasticsearch-整合SpringBoot。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

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

一、整合检索服务

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

1.1 创建 gulimall-search 模块

全文检索-Elasticsearch-整合SpringBoot
点击 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.html
    public 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 {

    @Resource
    private RestHighLevelClient restHighLevelClient;

    @Test
    public void contextLoads() {
        System.out.println(restHighLevelClient);
    }

}

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

全文检索-Elasticsearch-整合SpringBoot

二、存储数据到 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;
}

控制台打印数据

全文检索-Elasticsearch-整合SpringBoot
测试数据存储到 es 成功

全文检索-Elasticsearch-整合SpringBoot

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.分析结果 response
   System.out.println(response.toString());
}

查看检索结果

全文检索-Elasticsearch-整合SpringBoot
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.分析结果 response
    System.out.println(response.toString());
}

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

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

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

全文检索-Elasticsearch-整合SpringBoot

整体测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class GulimallSearchApplicationTests {

    @Resource
    private RestHighLevelClient restHighLevelClient;

    @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.分析结果 response
        System.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
     */
    @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);
    }

    @Test
    public void contextLoads() {
        System.out.println(restHighLevelClient);
    }

    @Data
    class User{
        private String userName;
        private String gender;
        private Integer age;
    }

    @Data
    @ToString
    static 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;

    }
}

控制台输出文章来源地址https://www.toymoban.com/news/detail-473897.html

检索条件:{"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

到了这里,关于全文检索-Elasticsearch-整合SpringBoot的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • springboot+Elasticsearch实现word,pdf,txt内容抽取并高亮分词全文检索

    文章目录 需求 一、环境 二、功能实现 1.搭建环境 2.文件内容识别 三.代码         产品希望我们这边能够实现用户上传PDF,WORD,TXT之内得文本内容,然后用户可以根据附件名称或文件内容模糊查询文件信息,并可以在线查看文件内容         项目开发环境:           

    2023年04月09日
    浏览(47)
  • 09、全文检索 -- Solr -- SpringBoot 整合 Spring Data Solr (生成DAO组件 和 实现自定义查询方法)

    测试类使用 solrClient 进行添加、查询、删除文档的操作在这篇的代码基础上继续演示的 两篇文章的区别: 上一篇是通过SolrClient 连接 Solr,然后用 SolrClient 来调用查询方法进行全文检索 这一篇是 自定义dao组件,通过继承CrudRepository 接口,用 dao 接口来调用查询方法进行全文检

    2024年02月19日
    浏览(57)
  • 全文检索-Elasticsearch-进阶检索

    本文记录谷粒商城高级篇的 Elasticsearch 进阶检索部分,续上之前记录的 Elasticsearch入门篇。 ES 支持两种基本方式检索 : 一个是通过使用 REST request URI 发送搜索参数(uri + 检索参数) 另一个是通过使用 REST request body 来发送它们(uri + 请求体) 请求体中写查询条件,语法: 示例

    2024年02月03日
    浏览(88)
  • Elasticsearch 全文检索 分词检索-Elasticsearch文章四

    https://www.elastic.co/guide/en/enterprise-search/current/start.html https://www.elastic.co/guide/en/elasticsearch/reference/7.17/query-dsl-match-query.html Full text Query中,我们只需要把如下的那么多点分为3大类,你的体系能力会大大提升 很多api都可以查得到,我们只要大概知道有支持哪些功能 Elasticsearch 执行

    2024年02月14日
    浏览(52)
  • elasticsearch全文检索

    传送门 best_fields 传送门 most_fields 当查询多字段包含相同文本以不同方式分词的时候此参数最有用, 传送门 cross_fields phrase和phrase_prefix 传送门 传送门

    2024年02月07日
    浏览(47)
  • ElasticSearch-全文检索

    https://www.elastic.co/cn/what-is/elasticsearch 全文搜索属于最常见的需求,开源的Elasticsearch是目前全文搜索引擎的首选。 它可以快速地储存、搜索和分析海量数据。 维基百科、StackOverflow、Github都采用它。 Elastic的底层是开源库Lucene。但是,你没法直接用Lucene,必须自己写代码去调用

    2024年04月17日
    浏览(39)
  • ElasticSearch 实战:ElasticSearch文档全文检索

    Elasticsearch 实战:Elasticsearch 文档全文检索 全文检索是 Elasticsearch 的核心功能之一,它允许用户对文本内容进行高效的模糊搜索、词组匹配、同义词处理、停用词过滤等操作。以下是如何进行文档全文检索的详细步骤: **1. **全文匹配查询(Match Query) 最基础的全文检索查询是

    2024年04月11日
    浏览(51)
  • ES(Elasticsearch 全文检索)

    数据量大的时候 索引失效 =查询性能低 功能比较弱 对文档的内容进行分词,对词条创建索引,记录词条所在的文档信息根据词条查询到文档的id 从而查到文档 文档:每一条数据就是一条文档 词条:文档按照语义分成的词语 正向索引 根据文档的id创建索引 查询词条必须先找

    2024年02月05日
    浏览(58)
  • ElasticSearch全文检索原理及过程

            ElasticSearch的搜索引擎中,每个 文档都有一个对应的文档 ID ,文档内容被表示为一系列的集合。例如文档 1 经过分词,提取了 20 个, 每个都会记录它在文档中出现的次数和出现位置 。那么,倒排索引就是 到文档   ID 的映射 ,每个关键

    2023年04月17日
    浏览(46)
  • 全文检索学习之ElasticSearch学习笔记

    在非关系型数据库中,数据是非结构化的,如果直接去查找效率极低,全文检索将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。索引就是从非结构化数据中提取出的然后重新组

    2023年04月11日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包