草庐IT

SpringBoot集成ElasticSearch

皮蛋不吃粥 2023-10-09 原文

SpringBoot集成ElasticSearch

序言

本章需要你在掌握基本的SpringBoot、JPA和一些ElasticSearch(以下简称:“Es”)的知识下进行服用。

环境

SpringBoot :2.2.6.RELEASE
Es:6.8.7(集群-3节点,且安装了ik分词器)
kibana 6.8.7

说明

测试环境的Es是6.8.7的3节点,代码相关依赖也是和Es服务端保持一致。当然大版本的6和7 Es的Api还是有些区别,具体Api的使用可以去官网进行翻阅,这里是以6.8版本进行讲解。

开始搭建

基本依赖

	 	<parent>
	        <groupId>org.springframework.boot</groupId>
	        <artifactId>spring-boot-starter-parent</artifactId>
	        <version>2.2.6.RELEASE</version>
	        <relativePath/> <!-- lookup parent from repository -->
	    </parent>

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
         <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
        </dependency>

yml配置

server:
  port: 8801
spring:
  application:
    name: esSpringboot
  elasticsearch:
    rest:
      uris: 192.168.1.195:9200,192.168.1.195:9201,192.168.1.195:9202 #设置集群

如何使用

实体

@Document(indexName = "student",type = "_doc",replicas = 0,shards = 3)
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Student implements Serializable {

    private static final long serialVersionUID = -1479160581341748052L;

    /*ik_smart 粗精度,ik_max_word 细精度*/
    @Field(type = FieldType.Text,searchAnalyzer = "ik_smart",analyzer = "ik_max_word")
    private String name;

    /*text类型开启统计的时候需要设置属性fielddata = true 正排索引*/
    @Field(type = FieldType.Long)
    private Integer age;

    @Field(type = FieldType.Text)
    private String testNumber;

    @Id
    @Field(type = FieldType.Keyword)
    private String id;

    @Field(type =  FieldType.Keyword)
    private String email;

    @Field(type =  FieldType.Date,format = DateFormat.custom,pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(shape =JsonFormat.Shape.STRING,pattern ="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    private Date birthDay;

}

这里需要你已经掌握Es的常用数据类型。

使用Repository

@Repository
public interface StudentRepository extends ElasticsearchRepository<Student,String> {

}

测试

批量添加

 public String saveBatch(){
        Faker faker = new Faker(Locale.CHINA);
        List<Student> collect = Stream.generate(() -> Student.builder()
                .age(faker.random().nextInt(1, 100))
                .email(faker.internet().emailAddress())
                .name(faker.name().username())
                .testNumber(faker.random().nextInt(1, 100)+"")
                .birthDay(new Date())
                .build()
        ).limit(1000).collect(Collectors.toList());
        studentRepository.saveAll(collect);
        return "ok";
    }

添加完成后我们在对应的kibana上面可以看到对应的Student索引和数据

执行指令查看添加数据的结果

POST /student/_search
{
  "query":{
    "match_all": {}
  }
}

结果

根据id查询

public Student getById( Long id){
        Optional<Student> byId = studentRepository.findById(id + "");
        return byId.get();
    }

根据id删除

public String removeById( Long id){
        studentRepository.deleteById(id + "");
        return "ok";
    }

当然也可以在Repository写一些Es的DSL查询语句

使用DSL

使用@Query 注解

    @Query("{\n" +
            "    \"term\": {\n" +
            "      \"name.keyword\": \"?0\"\n" +
            "    }\n" +
            "  }")
    List<Student> findStudentByName(String name);

复杂查询

  • 分页
  • 布尔
  • term
  • multiMatch
  • matchPhrase
  • fuzzy
  • regep
  • range
        Pageable pageable = PageRequest.of(0, 5);//分页
        BoolQueryBuilder boolQuery= boolQuery()
                /*term查询*/
//                .must(QueryBuilders.termQuery("name", student.getName()))
                /*range查询*/
                .must(QueryBuilders.rangeQuery("age").gte(0).lte(100))
                /*multiMatch*/
//                .must(QueryBuilders.multiMatchQuery(student.getEmail(), "name","email" ).operator(Operator.OR))
                /*matchPhraseQuery :紧邻查询,slop:允许间隔的单词个数*/
//                .must(QueryBuilders.matchPhraseQuery("name",student.getName()).slop(1))
                /*模糊匹配:查询的词也会分词 https://blog.csdn.net/weixin_42692506/article/details/101555035*/
//                .must(QueryBuilders.fuzzyQuery("name", "21").fuzziness(Fuzziness.AUTO))
                /*正则查询 [1-9] https://blog.csdn.net/u010483897/article/details/90485332*/
//                .must(QueryBuilders.regexpQuery("name", student.getName()))
                ;
                 SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withPageable(pageable)
                .withQuery(boolQuery)
                .build();
                Page<Student> search = studentRepository.search(searchQuery);
                List<Student> result= search.getContent();

聚合

  • 平均值
  • 求和
  • 最大值
  • 最小值
  • 范围
  • 时间范围
  • 时间间隔
  • 数值范围
    SearchQuery searchQuery = new NativeSearchQueryBuilder()
                /*name:统计的名称,field:统计的字段*/
                .addAggregation(AggregationBuilders.avg("ageAvg").field("age"))//平均值
                .addAggregation(AggregationBuilders.sum("ageSum").field("age"))//求和
                .addAggregation(AggregationBuilders.count("ageCount").field("age"))//有age的数目
                .addAggregation(AggregationBuilders.max("ageMax").field("age"))//最大值
                .addAggregation(AggregationBuilders.min("ageMin").field("age"))//最小值
                .addAggregation(AggregationBuilders.percentiles("agePercentiles").field("age"))//年龄百分比
                .addAggregation(AggregationBuilders.cardinality("ageCardinality").field("age"))//去重统计有多少数量
                .addAggregation(AggregationBuilders.terms("ageTerms").field("age").size(Integer.MAX_VALUE))//统计有相同age
                .addAggregation(AggregationBuilders.range("ageRange").field("age").addRange(0, 20)
                        .addRange(20, 40)
                        .addRange(40, 60)
                        .addRange(60, 80)
                )//查询年龄20~40,40~60,60~80范围统计
                .addAggregation(AggregationBuilders.dateRange("birthDayDateRange").field("birthDay").addRange("now/y-1y", "now/y")  //  now/y:当前年的1月1日  now:当前时间
                        .addRange("now/y-2y", "now/y-1y")  //  now/y-1y:当前年上一年的1月1日
                        .addRange("now/y-3y", "now/y-2y")
                        .format("yyyy-MM-dd"))//根据年统计
                /*年龄间隔统计 开始如果为20则后续设置统计就是20 22 24 26 28 30*/
                .addAggregation(AggregationBuilders.histogram("age_histogram_count")
                        .field("age")
                        .interval(20))
                /*时间统计 一定是对时间字段的统计,format是设置返回的key按照什么时间格式返回
                * 同时统计对应时间的年龄值合计
                * */
                .addAggregation(AggregationBuilders.dateHistogram("ageDateHistogram")
                        .field("birthDay")
                        .dateHistogramInterval(DateHistogramInterval.YEAR)
                        .format("yyyy-MM-dd HH:mm:ss")
                        .subAggregation(AggregationBuilders.sum("ageDateHistogramSum").field("age"))
                )
                   
AggregatedPage<Student> search = (AggregatedPage<Student>) studentRepository.search(searchQuery);
Aggregations aggregations = search.getAggregations();
Map<String, Aggregation> result= aggregations.getAsMap(); #获取聚合数据

参考

https://www.elastic.co/guide/cn/elasticsearch/guide/current/foreword_id.html

有关SpringBoot集成ElasticSearch的更多相关文章

  1. ruby-on-rails - 如何使辅助方法在 Rails 集成测试中可用? - 2

    我在app/helpers/sessions_helper.rb中有一个帮助程序文件,其中包含一个方法my_preference,它返回当前登录用户的首选项。我想在集成测试中访问该方法。例如,这样我就可以在测试中使用getuser_path(my_preference)。在其他帖子中,我读到这可以通过在测试文件中包含requiresessions_helper来实现,但我仍然收到错误NameError:undefinedlocalvariableormethod'my_preference'.我做错了什么?require'test_helper'require'sessions_hel

  2. ruby-on-rails - 我如何将 Hoptoad 与 DelayedJob 和 DaemonSpawn 集成? - 2

    我一直很高兴地使用DelayedJob习惯用法:foo.send_later(:bar)这会调用DelayedJob进程中对象foo的方法bar。我一直在使用DaemonSpawn在我的服务器上启动DelayedJob进程。但是...如果foo抛出异常,Hoptoad不会捕获它。这是任何这些包中的错误...还是我需要更改某些配置...或者我是否需要在DS或DJ中插入一些异常处理来调用Hoptoad通知程序?回应下面的第一条评论。classDelayedJobWorker 最佳答案 尝试monkeypatchingDelayed::W

  3. jenkins部署1--jenkins+gitee持续集成 - 2

    前置步骤我们都操作完了,这篇开始介绍jenkins的集成。话不多说,看操作1、登录进入jenkins后会让你选择安装插件,选择第一个默认的就行。安装完成后设置账号密码,重新登录。2、配置JDK和Git都需要执行路径,所以需要先把执行路径找到,先进入服务器的docker容器,2.1JDK的路径root@69eef9ee86cf:/usr/bin#echo$JAVA_HOME/usr/local/openjdk-82.2Git的路径root@69eef9ee86cf:/#whichgit/usr/bin/git3、先配置JDK和Git。点击:ManageJenkins>>GlobalToolCon

  4. ruby - Rails Elasticsearch 聚合 - 2

    不知何故,我似乎无法获得包含我的聚合的响应...使用curl它按预期工作:HBZUMB01$curl-XPOST"http://localhost:9200/contents/_search"-d'{"size":0,"aggs":{"sport_count":{"value_count":{"field":"dwid"}}}}'我收到回复:{"took":4,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":90,"max_score":0.0,"hits":[]},"a

  5. 三分钟集成 TapTap 防沉迷 SDK(Unity 版) - 2

    三分钟集成Tap防沉迷SDK(Unity版)一、SDK介绍基于国家对上线所有游戏必须增加防沉迷功能的政策下,TapTap推出防沉迷SDK,供游戏开发者进行接入;允许未成年用户在周五、六、日以及法定节假日晚上8:00-9:00进行游戏,防沉谜时间段进入游戏会弹窗进行提示!开发环境要求:Unity2019.4或更高版本iOS10或更高版本Android5.0(APIlevel21)或更高版本🔗Unity集成Demo参考链接🔗UnityTapSDK功能体验APK下载链接二、集成前准备1.创建应用进入开发者后台,按照提示开始创建应用;2.开通服务在使用TDS实名认证和防沉迷服务之前,需要在上面创建的应

  6. elasticsearch源码关于TransportSearchAction【阶段三】 - 2

    1.回顾.TransportServicepublicclassTransportServiceextendsAbstractLifecycleComponentTransportService:方法:1publicfinalTextendsTransportResponse>voidsendRequest(finalTransport.Connectionconnection,finalStringaction,finalTransportRequestrequest,finalTransportRequestOptionsoptions,TransportResponseHandlerT>

  7. ruby-on-rails - RailsTutorial - 第 8.4.3 章 - 在集成测试中添加用户后未清除测试数据库 - 2

    我被这个难住了。到目前为止教程中的一切都进行得很顺利,但是当我将这段代码添加到我的/spec/requests/users_spec.rb文件中时,事情开始变得糟糕:describe"success"doit"shouldmakeanewuser"dolambdadovisitsignup_pathfill_in"Name",:with=>"ExampleUser"fill_in"Email",:with=>"ryan@example.com"fill_in"Password",:with=>"foobar"fill_in"Confirmation",:with=>"foobar"cl

  8. ruby-on-rails - 使用 Rails (Tire) 和 ElasticSearch 进行模糊字符串匹配 - 2

    我有一个Rails应用程序,现在设置了ElasticSearch和Tiregem以在模型上进行搜索,我想知道我应该如何设置我的应用程序以对模型中的某些索引进行模糊字符串匹配。我将我的模型设置为索引标题、描述等内容,但我想对其中一些进行模糊字符串匹配,但我不确定在何处进行此操作。如果您想发表评论,我将在下面包含我的代码!谢谢!在Controller中:defsearch@resource=Resource.search(params[:q],:page=>(params[:page]||1),:per_page=>15,load:true)end在模型中:classResource'Us

  9. ruby-on-rails - 将 Angular JS 与 Rails 集成 - 2

    我需要一些指导来了解如何将Angular整合到rails中。选择Rails的原因:我喜欢他们偏执的做事方式。还有迁移,gem真的很酷。使用angular的原因:我正在研究和寻找最适合SPA的框架。Backbone似乎太抽象了。我不得不在Angular和Ember之间做出选择。我首先开始阅读Angular,它对我来说很有意义。所以我从来没有去读过关于ember的文章。使用Angular和Rails的原因:我研究并尝试使用小型框架,例如grape、slim(是的,我也使用php)。但我觉得需要坚持项目的长期范围。我个人喜欢用Rails的方式做事。这就是我需要帮助的地方,我在Rails4中有

  10. ruby - 在 Maven 集成中运行 Ruby 单元测试 - 2

    有没有人有在Maven中运行用Ruby编写的单元测试的经验。任何输入,如要使用的库/maven插件,将不胜感激!我们已经在使用Maven+hudson+Junit。但是我们正在引入Ruby单元测试,找不到任何同样好的组合。 最佳答案 我建议让Maven使用ExecMavenPlugin启动rake测试(exec:exec目标)并使用ci_reportergem生成单元测试结果的XML文件,Hudson、Bamboo等可以读取该文件,以与JUnit测试相同的格式显示测试结果。如果您不需要使用mvntest运行Ruby测试,您也可以只使

随机推荐