zoukankan      html  css  js  c++  java
  • Elasticsearch学习笔记

    引自狂神说:https://www.bilibili.com/video/BV17a4y1x7zq

    1.Lucene创始人Doug Cutting

    1985年,Cutting毕业于美国斯坦福大学。他并不是一开始就决心投身IT行业的,在大学时代的头两年,Cutting学习了诸如物理、地理等常规课程。因为学费的压力,Cutting开始意识到,自己必须学习一些更加实用、有趣的技能。这样,一方面可以帮助自己还清贷款,另一方面,也是为自己未来的生活做打算。因为斯坦福大学座落在IT行业的“圣地”硅谷,所以学习软件对年轻人来说是再自然不过的事情了。

    Cutting的第一份工作是在Xerox做实习生,Xerox当时的激光扫描仪上运行着三个不同的操作系统,其中的一个操作系统还没有屏幕保护程序。因此,Cutting就开始为这套系统开发屏幕保护程序。由于这套程序是基于系统底层开发的,所以 其他同事可以给这个程序添加不同的主题。这份工作给了Cutting一定的满足感,也是他最早的“平台”级的作品。
    尽管Xerox让Cutting积累了不少技术知识,但他却认为,自己当时搞的这些研究只是纸 上谈兵,没有人试验过这些理论的可实践性。于是,他决定勇敢地迈出这一步,让搜索技术可以为更多人所用。

    1997年底,Cutting开始以每周两天的时间投入,在家里试着用Java把这个想法变成现实,不久之后,Lucene诞生了。作为第一个提供全文文本搜索的开源函数库,Lucene的伟大自不必多言。之后,Cutting再接再厉,在 Lucene的基础上将开源的思想继续深化。

    2004年,Cutting和同为程序员出身的Mike Cafarella决定开发一款可以代替当时的主流搜索产品的开源搜索引擎,这个项目被命名为Nutch。Doug Cutting 希望以开源架构开发出一套搜索技术,类似于现在的 Google Search 或是微软的 Bing,刚好 2004 年 Google Labs 发布了关于自家大数据分析、MapReduce 算法的论文。Doug Cutting 利用 Google 公开的技术扩充他已经开发出来的 Lucene 搜索技术,进而打造出了 Hadoop。

    生活中,可能所有人都间接用过他的作品,他是Lucene、Nutch 、Hadoop等项目的发起人。是他,把高深莫测的搜索技术形成产品,贡献给普罗大众;还是他,打造了目前在云计算和大数据领域里如日中天的Hadoop。

    2.什么是Elasticsearch

    Elasticsearch 是一个分布式的开源搜索和分析引擎,适用于所有类型的数据,包括文本、数字、地理空间、结构化和非结构化数据。

    Elasticsearch 在 Apache Lucene 的基础上开发而成,由 Elasticsearch N.V.(即现在的 Elastic)于 2010 年首次发布。

    Elasticsearch 以其简单的 REST 风格 API、分布式特性、速度和可扩展性而闻名,是 Elastic Stack 的核心组件;

    Elastic Stack 是适用于数据采集、充实、存储、分析和可视化的一组开源工具。

    人们通常将 Elastic Stack 称为 ELK Stack(代指 Elasticsearch、Logstash 和 Kibana),目前 Elastic Stack 包括一系列丰富的轻量型数据采集代理,这些代理统称为 Beats,可用来向 Elasticsearch 发送数据。

    传统搜索和实时搜索

    传统搜索:从静态数据库中搜索出符合条件的结果,这种结果往往是不可变的、静态的。

    实时搜索:搜索的结果是实时变化的。

    Lucene、Solr和Elasticsearch的关系

    概念不同:

    1. Lucene是一套信息检索工具包(jar包),并不包含搜索引擎系统,它包含了索引结构、读写索引工具、相关性工具、排序等功能,因此在使用Lucene时仍需要关注搜索引擎系统,例如数据获取、解析、分词等方面的东西。
    2. Solr是一个有HTTP接口的基于Lucene的查询服务器,封装了很多Lucene细节,自己的应用可以直接利用诸如 .../solr?q=abc 这样的HTTP GET/POST请求去查询,维护修改索引。
    3. Elasticsearch也是一个建立在全文搜索引擎 Apache Lucene基础上的搜索引擎。采用的策略是分布式实时文件存储,并将每一个字段都编入索引,使其可以被搜索。

    联系:Solr和ES都是基于Lucene实现的!

    区别:

    1. solr利用zookpper进行分布式管理,而elasticsearch自身带有分布式协调管理功能;
    2. solr比elasticsearch实现更加全面,solr官方提供的工具更多,而elasticsearch本身更注重于核心功能,高级功能多由第三方插件提供;例如图形化界面可以使用Kibana友好支撑;
    3. solr在传统的搜索应用中表现好于elasticsearch,而elasticsearch在实时搜索应用方面比solr表现好;
    4. Solr支持更多的数据格式,比如json、xml、csv等,但是ES只支持json格式;
    5. Solr比较成熟,有一个更成熟的用户、开发者和贡献者社区;ES相对开发维护者较少,更新快,学习使用成本较高,但是将来的一个趋势。

    为什么使用Elasticsearch

    • Elasticsearch 很快。 由于 Elasticsearch 是在 Lucene 基础上构建而成的,所以在全文本搜索方面表现十分出色。Elasticsearch 同时还是一个近实时的搜索平台,这意味着从文档索引操作到文档变为可搜索状态之间的延时很短,一般只有一秒。因此,Elasticsearch 非常适用于对时间有严苛要求的用例,例如安全分析和基础设施监测。
    • Elasticsearch 具有分布式的本质特征。 Elasticsearch 中存储的文档分布在不同的容器中,这些容器称为分片,可以进行复制以提供数据冗余副本,以防发生硬件故障。Elasticsearch 的分布式特性使得它可以扩展至数百台(甚至数千台)服务器,并处理 PB 量级的数据。
    • Elasticsearch 包含一系列广泛的功能。 除了速度、可扩展性和弹性等优势以外,Elasticsearch 还有大量强大的内置功能(例如数据汇总和索引生命周期管理),可以方便用户更加高效地存储和搜索数据。
    • Elastic Stack 简化了数据采集、可视化和报告过程。 通过与 Beats 和 Logstash 进行集成,用户能够在向 Elasticsearch 中索引数据之前轻松地处理数据。同时,Kibana 不仅可针对 Elasticsearch 数据提供实时可视化,同时还提供 UI 以便用户快速访问应用程序性能监测 (APM)、日志和基础设施指标等数据。

    ELK

    ELK是Elasticsearch、Logstash、Kibana三大开源框架首字母大写简称。市面上也被成为Elastic Stack。其中Elasticsearch是一个基于Lucene、分布式、通过Restful方式进行交互的近实时搜索平台框架。像类似百度、谷歌这种大数据全文搜索引擎的场景都可以使用Elasticsearch作为底层支持框架,可见Elasticsearch提供的搜索能力确实强大,市面上很多时候我们简称Elasticsearch为es。Logstash是ELK的中央数据流引擎,用于从不同目标(文件/数据存储/MQ)收集的不同格式数据,经过过滤后支持输出到不同目的地(文件/MQ/redis/elasticsearch/kafka等)。Kibana可以将elasticsearch的数据通过友好的页面展示出来,提供实时分析的功能。

    市面上很多开发只要提到ELK能够一致说出它是一个日志分析架构技术栈总称,但实际上ELK不仅仅适用于日志分析,它还可以支持其它任何数据分析和收集的场景,日志分析和收集只是更具有代表性。并非唯一性。

    3.ES的安装及head插件安装

    声明:JDK1.8是最低要求,需要提前安装nodejs、grunt、pathomjs。

    npm -v	#查看npm版本
    node -v	#查看node版本
    npm install -g grunt -cli	#安装grunt
    npm install	#按照package.json安装所需要的组件放在生成的node_modules文件夹中
    

    windows下安装

    1. 解压即可;

    2. 熟悉目录;

    bin	#启动目录
    config	#配置文件
    	log4j2.properties	#日志配置文件
    	jvm.options	#java虚拟机相关配置
    	elasticsearch.yml	#ES配置文件,默认端口9200
    lib	#相关jar包
    modules	#功能模块
    plugins	#插件
    logs	#日志
    
    1. 在D:Elasticsearchelasticsearch-7.6.0in路径下使用cmd运行elasticsearch.bat,然后访问端口9200即可。

    访问成功的页面:

    解决跨域问题

    在elasticsearch.yml文件中增加以下配置:

    http.cors.enabled: true	#启用HTTP端口,允许跨源REST请求。
    http.cors.allow-origin: "*"	#允许REST请求来自何处。
    

    遇到的问题:

    [2020-05-04T12:52:25,721][ERROR][o.e.b.Bootstrap          ] [QD-PC] Exception
    org.elasticsearch.ElasticsearchException: X-Pack is not supported and Machine Learning is not available for [windows-x86]; you can use the other X-Pack features (unsupported) by setting xpack.ml.enabled: false in elasticsearch.yml
    
    解决方式:在elasticsearch.yml文件中增加以下配置:
    xpack.ml.enabled: false
    

    安装head插件

    1. 下载head插件:https://github.com/mobz/elasticsearch-head,下载zip安装包;
    2. 解压到ES同级目录下:D:Elasticsearch;
    3. 在dos窗口进入到head路径下D:Elasticsearchelasticsearch-head-master,使用命令npm install安装相关组件;
    4. 使用命令npm start启用服务,访问9100端口即可。

    访问成功的页面:

    4.ES核心概念

    4.1 基本概念

    ES本质上是一个分布式数据库,允许多台服务器协同工作,每台服务器可以运行多个ES实例。

    集群、节点:单个 ES 实例称为一个节点(node)。一组节点构成一个集群(cluster)。默认的集群名称就是elasticsearch。

    索引(数据库):索引是含有相同属性的文档集合,索引在ES中是通过一个名字来识别的,必须是英文字母小写,且不含中划线。ES会索引所有字段,经过处理后写入一个倒排索引(Inverted Index)。查找数据的时候,直接查找该索引。

    类型(表):一个索引可以定义一个或多个类型,文档必须属于一个类型。

    文档(一行):文档是可以被索引的基本数据单位

    分片:每个索引都有多个分片,每个分片都是一个lucene索引。分片的好处:分摊索引的搜索压力,分片还支持水平的拓展和拆分以及分布式的操作,可以提高搜索和其他处理的效率。

    备份:拷贝一个分片就完成了分片的备份,备份的好处:当主分片失败或者挂掉,备份就可以代替分片进行操作,进而提高了ES的可用性,备份的分片还可以进行搜索操作,以分摊搜索的压力。ES在创建索引时,默认创建5个分片,一份备份,可以修改,分片的数量只能在创建索引的时候指定,索引创建后就不能修改分片的数量了,而备份是可以动态修改的。

    ES(面向文档)和关系型数据库(Relation Database RDB)的比较

    RDB ES
    数据库(database) 索引(indices)
    表(table) 类型(type)
    行(row) 文档(document)
    列(column) 字段(field)

    ES(集群)中可以包含多个索引(数据库),每个索引中可以包含多个类型(表),每个类型包含多个文档(行),每个文档又包含多个字段(列)。

    物理设计:ES后台把每个索引划分成多个分片,每个分片可以在集群中的不同服务器间迁移。

    逻辑设计:一个索引类型中,包含多个文档,比如文档1,文档2...。当我们索引一篇文档时,可以这样找到它:索引->类型->文档ID,通过这样的方式就能找到具体的文档。注意:ID不必是整数,实际上它是一个字符串。

    4.2 正排索引和倒排索引

    正排索引:文档ID为key,表中记录每个关键词出现的次数,查找时扫描表中的每个文档中字的信息,直到找到所有包含查询关键字的文档。

    倒排索引:

    1. 由不同的索引词(index term)组成的索引表,称为“词典”(lexicon)。其中包含了各种词汇,以及这些词汇的统计信息(如出现频率nDocs),这些统计信息可以直接用于各种排名算法。
    2. 由每个索引词出现过的文档集合,以及命中位置等信息构成。也称为“记录表”。就是正排索引产生的那张表。当然这部分可以没有。具体看自己的业务需求了。
    正排索引 倒排索引
    搜索方式 通过key找value 通过value找key
    优缺点 易维护 构建索引的时候较为耗时且维护成本较高
    搜索的耗时太长 搜索耗时短

    ES使用了倒排索引结构,这种结构适用于快速的全文搜索。一个索引由文档中所有不重复的列表组成,对于每一个词,都有一个包含它的文档列表。

    5.IK分词器

    分词:从一串文本中切分出一个一个的词条,并对每个词条进行标准化。默认的中文分词是把每个字看作一个分词,这显然不符合要求,所以一般使用IK分词器来解决该问题。

    IK分词器提供了两种分词算法:ik_smart(最少切分)和ik_max_word(最细粒度划分)。

    下载安装

    1. 下载地址:https://github.com/medcl/elasticsearch-analysis-ik/releases,找到和ES一样的版本号下载;
    2. 安装地址:将安装包解压到ES安装目录的plugins的ik文件夹下;
    3. 重启ES,访问5601端口即可。
    #在ES的bin目录中,使用elasticsearch-plugin可以查看插件
    PS D:Elasticsearchelasticsearch-7.6.0in> .elasticsearch-plugin list
    future versions of Elasticsearch will require Java 11; your Java version from [C:Program Files (x86)Javajdk1.8.0_181jre] does not meet this requirement
    ik
    

    两种算法结果:

    # 使用ik_smart
    GET _analyze
    {
      "analyzer":"ik_smart",
      "text": "中国子弟兵"
    }
    运行结果:
    {
      "tokens" : [
        {
          "token" : "中国子弟兵",
          "start_offset" : 0,
          "end_offset" : 5,
          "type" : "CN_WORD",
          "position" : 0
        }
      ]
    }
    # 使用ik_max_word
    GET _analyze
    {
      "analyzer":"ik_max_word",
      "text": "中国子弟兵"
    }
    运行结果:
    {
      "tokens" : [
        {
          "token" : "中国子弟兵",
          "start_offset" : 0,
          "end_offset" : 5,
          "type" : "CN_WORD",
          "position" : 0
        },
        {
          "token" : "中国",
          "start_offset" : 0,
          "end_offset" : 2,
          "type" : "CN_WORD",
          "position" : 1
        },
        {
          "token" : "国共",
          "start_offset" : 1,
          "end_offset" : 3,
          "type" : "CN_WORD",
          "position" : 2
        },
        {
          "token" : "子弟兵",
          "start_offset" : 2,
          "end_offset" : 5,
          "type" : "CN_WORD",
          "position" : 3
        },
        {
          "token" : "共产",
          "start_offset" : 2,
          "end_offset" : 4,
          "type" : "CN_WORD",
          "position" : 4
        },
        {
          "token" : "党",
          "start_offset" : 4,
          "end_offset" : 5,
          "type" : "CN_CHAR",
          "position" : 5
        }
      ]
    }
    #对于某些特殊含义的分词,系统自带的词典里面没有收录,需要自己创建字典。
    

    创建自己的字典

    1. 创建my.dic,加入自己需要的分词;
    令狐冲
    狂神说
    
    1. 在ik分词器的config中修改配置文件IKAnalyzer.cfg.xml,D:Elasticsearchelasticsearch-7.6.0pluginsikconfig.
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
    <properties>
    	<comment>IK Analyzer 扩展配置</comment>
    	<!--用户可以在这里配置自己的扩展字典 -->
    	<entry key="ext_dict">my.dic</entry>
    	 <!--用户可以在这里配置自己的扩展停止词字典-->
    	<entry key="ext_stopwords"></entry>
    	<!--用户可以在这里配置远程扩展字典 -->
    	<!-- <entry key="remote_ext_dict">words_location</entry> -->
    	<!--用户可以在这里配置远程扩展停止词字典-->
    	<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
    </properties>
    

    然后继续使用kibana查询即可看到字典中的分词了。

    6.Rest风格说明

    一种软件架构风格,而不是标准,只是提供了一组设计原则和约束条件。

    它主要用于客户端和服务端交互类的软件,基于这个风格设计的软件可以更简洁、更有层次、更易于实现缓存等机制。

    基本命令说明:

    method url地址 描述
    PUT localhost:9200/索引名称/类型名称/文档id 创建文档(指定文档id)
    POST localhost:9200/索引名称/类型名称 创建文档(随机文档id)
    POST localhost:9200/索引名称/类型名称/文档id/_update 修改文档
    DELETE localhost:9200/索引名称/类型名称/文档id 删除文档
    GET localhost:9200/索引名称/类型名称/文档id 查询文档(通过文档id)
    POST localhost:9200/索引名称/类型名称/_search 查询所有数据

    基础测试

    # PUT /索引名/类型名/文档id {请求体}
    PUT /kss/type1/1
    {
      "name":"令狐冲",
      "age":3
    }
    #修改一个文档的两种方式 PUT、POST都可以,但是PUT操作如果某些字段没有修改的话自动修改成空值,POST就比较灵活,可以随意修改一个或者多个字段。
    PUT /kss/type1/1
    {
      "name":"令狐冲1",
      "age":18
    }
    POST /kss/type1/1/_update
    {
      "doc":{
          "name":"令狐冲2",
          "age":20
      }
    }
    #删除索引
    DELETE kss
    
    PUT kss/user/1
    {
      "name":"令狐冲",
      "age":18,
      "desc":["技术宅","分享"]
    }
    
    PUT kss/user/2
    {
      "name":"张三",
      "age":3,
      "desc":["法外狂徒","渣男"]
    }
    
    PUT kss/user/3
    {
      "name":"李四",
      "age":4,
      "desc":["靓仔","旅游"]
    }
    
    PUT kss/user/3
    {
      "name":"李五"
    }
    
    POST kss/user/3/_update
    {
      "doc":{
        "name":"李五"
      }
    }
    #查询
    GET kss/user/_search 	#查询所有
    GET kss/user/_search?q=name:令狐冲 	#精准查询
    #查询某些字段
    GET kss/user/_search
    {
      "query": {
        "match": {
          "name": "令"	#过滤条件
        }
      },
      "_source":["name","age"]	#查询某些字段
    }
    #排序
    GET kss/user/_search
    {
      "query": {
        "match": {
          "name": "令"
        }
      },
      "sort": [
        {
          "age": {
            "order": "desc"
          }
        }
      ]
    }
    #分页查询
    GET kss/user/_search
    {
      "query": {
        "match": {
          "name": "令"
        }
      },
      "from": 0, #从第几条数据开始,数据下标还是从0开始
      "size": 3	#返回多少数据
    }
    #多个条件精确查询
    GET kss/user/_search
    {
     "query": {
       "bool": {
         "must": [ 	#must相当于mysql中的and
           {
             "match": {
               "name": "令狐冲"
             }
           },
           {
             "match": {
               "age": "25"
             }
           }
         ]
       }
     } 
    }
    GET kss/user/_search
    {
     "query": {
       "bool": {
         "should": [		#should相当于mysql中的or
           {
             "match": {
               "name": "令狐冲"
             }
           },
           {
             "match": {
               "age": "25"
             }
           }
         ]
       }
     } 
    }
    GET kss/user/_search
    {
      "query": {
        "bool": {
          "must_not": [ 	#must_not相当于mysql中的not
            {
              "match": {
                "age": "25"
              }
            }
          ]
        }
      }
    }
    GET kss/user/_search
    {
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "name": "令狐冲"
              }
            }
          ],
          "filter": { #filter相当于mysql中的between
            "range": {
              "age": {
                "gte": 10,
                "lte": 20
              }
            }
          }
        }
      }
    }
    GET kss/user/_search
    {
      "query": {
        "match": {
          "desc": "宅 技术 游一游" #多个条件使用空格隔开
        }
      }
    }
    
    GET _cat/indices?v	#查看所有索引的状态和内存信息
    GET _cat/health	#查看ES的状态
    

    精确查询:term查询是直接通过倒排索引指向的词条进行精确查找的。

    关于分词:

    • term,直接精确查询的;
    • match,会使用分词器解析(先分析文档,然后再通过分析的文档进行查询)

    两个类型:text(会被分词器解析)和keyword(不会被分词器解析)、

    7.集成SpringBoot

    1. 到相关的依赖,版本一定要和安装的ES版本一致;

    2. 找到ES官方提供的对象,创建config包,创建配置类来提供对象;

    package com.kss.config;
    
    import org.apache.http.HttpHost;
    import org.elasticsearch.client.RestClient;
    import org.elasticsearch.client.RestHighLevelClient;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class ElasticsearchClientConfig {
        //spring里面<beans id="restHighLevelClient" class="RestHighLevelClient">
        @Bean
        public RestHighLevelClient restHighLevelClient() {
            RestHighLevelClient client = new RestHighLevelClient(
                    RestClient.builder(
                            new HttpHost("127.0.0.1",
                                    9200, "http")));
            return client;
        }
    }
    
    1. 测试。
    package com.kss;
    
    import com.alibaba.fastjson.JSON;
    import com.kss.pojo.User;
    import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
    import org.elasticsearch.action.bulk.BulkRequest;
    import org.elasticsearch.action.bulk.BulkResponse;
    import org.elasticsearch.action.delete.DeleteRequest;
    import org.elasticsearch.action.delete.DeleteResponse;
    import org.elasticsearch.action.get.GetRequest;
    import org.elasticsearch.action.get.GetResponse;
    import org.elasticsearch.action.index.IndexRequest;
    import org.elasticsearch.action.index.IndexResponse;
    import org.elasticsearch.action.search.SearchRequest;
    import org.elasticsearch.action.search.SearchResponse;
    import org.elasticsearch.action.support.master.AcknowledgedResponse;
    import org.elasticsearch.action.update.UpdateRequest;
    import org.elasticsearch.action.update.UpdateResponse;
    import org.elasticsearch.client.RequestOptions;
    import org.elasticsearch.client.RestHighLevelClient;
    import org.elasticsearch.client.indices.CreateIndexRequest;
    import org.elasticsearch.client.indices.CreateIndexResponse;
    import org.elasticsearch.client.indices.GetIndexRequest;
    import org.elasticsearch.common.unit.TimeValue;
    import org.elasticsearch.common.xcontent.XContentType;
    import org.elasticsearch.index.query.MatchAllQueryBuilder;
    import org.elasticsearch.index.query.QueryBuilders;
    import org.elasticsearch.search.SearchHit;
    import org.elasticsearch.search.builder.SearchSourceBuilder;
    import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.concurrent.TimeUnit;
    
    @SpringBootTest
    class kssEsApiApplicationTests {
    
        @Autowired
        @Qualifier("restHighLevelClient")
        private RestHighLevelClient client;
    
        //测试索引的创建
        @Test
        void textCreateIndex() throws IOException {
            //1、创建索引请求
            CreateIndexRequest request = new CreateIndexRequest("kss_index");
            //2、客户端执行请求 In
            CreateIndexResponse createIndexResponse =
                    client.indices().create(request, RequestOptions.DEFAULT);
            System.out.println(createIndexResponse);
        }
    
        //测试获取索引,判断是否存在这个索引
        @Test
        void textExistIndex() throws IOException {
            GetIndexRequest request =
                    new GetIndexRequest("kss_index");
            boolean exists = client.indices().
                    exists(request, RequestOptions.DEFAULT);
            System.out.println(exists);
        }
    
        //删除索引
        @Test
        void testDeleteIndex() throws IOException {
            DeleteIndexRequest request =
                    new DeleteIndexRequest("kss_index");
            AcknowledgedResponse delete = client.indices().
                    delete(request, RequestOptions.DEFAULT);
            System.out.println(delete.isAcknowledged());
        }
    
        //测试添加文档
        @Test
        void testAddDocument() throws IOException {
            //创建对象
            User user = new User("令狐冲", 3);
            //创建请求
            IndexRequest request = new IndexRequest("kss_index");
            //规则:PUT /kss_index/_doc/1
            request.id("1").timeout("1s");
            //将数据放入请求 json
            request.source(JSON.toJSONString(user), XContentType.JSON);
            //客户端发送请求,打印请求结果
            IndexResponse index = client.index(request, RequestOptions.DEFAULT);
            System.out.println(index.toString());
            System.out.println(index.status());
        }
    
        //测试文档是否存在
        @Test
        void testIsExists() throws IOException {
            GetRequest getRequest = new GetRequest("kss_index", "1");
            //不获取返回时_source的上下文
            getRequest.fetchSourceContext(new FetchSourceContext(false));
            getRequest.storedFields("_none_");
            boolean exists = client.exists(getRequest, RequestOptions.DEFAULT);
            System.out.println(exists);
        }
    
        //获得文档的信息
        @Test
        void testGetDocument() throws IOException {
            GetRequest request = new GetRequest("kss_index", "1");
            GetResponse getResponse =
                    client.get(request, RequestOptions.DEFAULT);
            System.out.println(getResponse.getSource());
            System.out.println(getResponse);
        }
    
        //更新文档的信息
        @Test
        void testUpdateRequest() throws IOException {
            UpdateRequest request = new UpdateRequest("kss_index", "1");
            request.timeout("1s");
            User user = new User("令狐冲学习Java", 18);
            request.doc(JSON.toJSONString(user), XContentType.JSON);
            UpdateResponse update =
                    client.update(request, RequestOptions.DEFAULT);
            System.out.println(update.status());
        }
    
        //删除文档记录
        @Test
        void testDeleteDocument() throws IOException {
            DeleteRequest request = new DeleteRequest("kss_index", "1");
            request.timeout("1s");
            DeleteResponse delete =
                    client.delete(request, RequestOptions.DEFAULT);
            System.out.println(delete.status());
        }
    
        //批量插入数据
        @Test
        void testBulkRequest() throws IOException {
            BulkRequest bulkRequest = new BulkRequest();
            bulkRequest.timeout("10s");
            ArrayList<User> userArrayList = new ArrayList<>();
            userArrayList.add(new User("令狐冲1", 1));
            userArrayList.add(new User("令狐冲2", 2));
            userArrayList.add(new User("令狐冲3", 3));
            userArrayList.add(new User("令狐冲4", 4));
            userArrayList.add(new User("令狐冲5", 5));
            userArrayList.add(new User("令狐冲6", 6));
            for (int i = 0; i < userArrayList.size(); i++) {
                bulkRequest.add(new IndexRequest("kss_index")
                        .id("" + (i + 1))
                        .source(JSON.toJSONString(userArrayList.get(i)),
                                XContentType.JSON));
            }
            BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT);
            System.out.println(bulk.hasFailures());//是否失败,返回false,代表成功
        }
    
        //查询
        @Test
        void testSearch() throws IOException {
            SearchRequest request = new SearchRequest("kss_index");
            //构建搜索条件
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            sourceBuilder.highlighter();
            //查询条件,可以使用QueryBuilders工具来构建
            //QueryBuilders.termQuery   精确查询
            //QueryBuilders.matchAllQuery   匹配所有
    //        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "令狐冲");
    //        sourceBuilder.query(termQueryBuilder);
            MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
            sourceBuilder.query(matchAllQueryBuilder);
            sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));//设置超时时间
            request.source(sourceBuilder);
            SearchResponse searchResponse = client.search(request, RequestOptions.DEFAULT);
            System.out.println(JSON.toJSONString(searchResponse.getHits()));
            System.out.println("-------------------------------------------");
            for (SearchHit documentFields:searchResponse.getHits().getHits()) {
                System.out.println(documentFields.getSourceAsMap());
            }
        }
    }
    
  • 相关阅读:
    最长上升序列,首尾连接
    带权并查集&&并查集
    开发者的小天地-1
    Binary Tree Maximum Path Sum
    Linked List Cycle II
    动归熟手题单
    java 正则表达式-忽略大小写与多行匹配
    KO之tab栏切换
    Vue中通过属性绑定为元素绑定style
    Vue中通过属性绑定为元素设置class
  • 原文地址:https://www.cnblogs.com/smalldong/p/14466476.html
Copyright © 2011-2022 走看看