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:\Elasticsearch\elasticsearch-7.6.0\bin路径下使用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:\Elasticsearch\elasticsearch-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:\Elasticsearch\elasticsearch-7.6.0\bin> .\elasticsearch-plugin list
future versions of Elasticsearch will require Java 11; your Java version from [C:\Program Files (x86)\Java\jdk1.8.0_181\jre] 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:\Elasticsearch\elasticsearch-7.6.0\plugins\ik\config.
<?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());
        }
    }
}
posted @ 2021-03-01 22:49  碧水云天4  阅读(213)  评论(0编辑  收藏  举报