ElasticSearch入门学习教程_elasticsearch.url配置文件-程序员宅基地

技术标签: java  elasticsearch  

前言

本片博客是本人通过观看狂神说的视频记录的笔记,以此记录方便需要时查阅。
视频地址:https://www.bilibili.com/video/BV17a4y1x7zq


1.ElasticSearch的简介

ElasticSearch,简称ES。ES是一个开源的高扩展分布式全文检索引擎,它可以近乎实时的存储、检索数据;本身的扩展性很好,可以扩展到上百台服务器,处理BP(大数据)级别的数据。ES也使用Java开发并使用Lucene作为其核心来实现所有缩影和搜索功能,但是它的目的是通过简单的RESTFul API来隐藏Lucene的复杂性,从而让全文搜索变得简单。

2.ElasticSearch安装及配置

2.1.基于Docker安装ElasticSearch

# 下载7.6.1版本的ElasticSearch镜像
docker pull elasticsearch:7.6.1
# 通过ElasticSearch镜像创建并容器
# ps:9200对外访问端口,9300通信端口
docker run -d --name es -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch

2.2.配置

# 进入elasticsearch容器内部
docker exec -it es /bin/bash
# 进入config目录,找到elasticsearch.yml文件
cd config
# 编辑elasticsearch.yml文件
vi elasticsearch.yml

详细如下图:
cluster.name:自定义集群名称
network.host:当前es节点绑定的ip地址,默认127.0.0.1,如果需要开放对外访问这个属性必须设置

以上两个是默认就有的

http.cors.enabled:是否支持跨域,默认事false
http.cors.allow-origin:当设置允许跨域,默认为*,表示支持所有域名,如果我们只是允许某些网站能访问,那么可以使用正则表达式。

在这里插入图片描述

2.2.1.elasticsearch.yml 配置文件
cluster.name: "docker-cluster"
network.host: 0.0.0.0
http.cors.enabled: true
http.cors.allow-origin: "*"
2.2.2.配置好重启容器
# 推出容器
exit
# 重启容器
docker restart es

2.3.浏览器访问localhost:9200

在这里插入图片描述

上图描述的就是ES的一些基本信息。包括名称、集群名称、集群ID、版本、打开方式、以及依赖程序的版本信息。

3.ElasticSearch目录结构说明

# 通过docker命令进入到容器内部
docker exec -it es /bin/bash
# 查看目录结构
ls -ll

详细如下图所示:

在这里插入图片描述

  • LICENSE.txt:证书描述文件
  • NOTICE.txt:产品使用注意事项
  • README.asciidoc:描述或使用文件
  • bin:启动文件
  • config:配置文件
    • log4j2:日志配置文件
    • jvm.options Java虚拟机相关的配置
    • elasticsearch.yml elasticsearch的配置文件
  • lib:相关依赖包
  • logs:日志
  • modules:功能模块
  • plugins:插件

4.使用可视化工具连接ElasticSearch

安装:elasticsearch-head
下载地址:https://github.com/mobz/elasticsearch-head

5.安装Kibana

5.1.Kibana简介

Kibana是一个针对ElasticSearch的开源分析急可视化平台,用来搜索、查看交互存储在ElasticSearch索引中的数据,使用Kibana可以通过各种图标进行高级数据分析及展示。Kibana让海量数据更容易理解。它操作简单,给予浏览器的用户界面可以快速创建仪表板实时显示Elasticsearch查询动态。设置Kibana非常简单。无需编码或者额外的基础架构,几分钟内就可以完成Kibana安装并启动Elasticsearch缩影监测

5.2.Docker安装Kibana

注意:Kibana的版本要和ElasticSearch的版本要保持一致

# 下载7.6.1版本的Kibana镜像
docker pull kibana:7.6.1
# 通过Kibana镜像创建容器,需要注意的是ELASTICSEARCH_URL=http://IP:9200 中的IP是elasticsearch所在服务器的IP
# 可以先通过如下命令获取elasticsearch所在服务器的IP
docker inspect --format '{
    { .NetworkSettings.IPAddress }}' es 
# 我这里得到的IP地址为:172.17.0.2
docker run --name kibana -d -p 5601:5601 --link es -e "ELASTICSEARCH_URL=http://172.17.0.2:9200" kibana:7.6.1

上述操作完成后,在浏览器中访问地址:localhost:5601。如果可以看到如下界面说明Kibana就已经安装好了

在这里插入图片描述

如果您访问地址看到的界面如下所示,说明创建的Kibana容器的指向IP没有elasticsearch容器IP。
此时我们可以通过修改Kibana的配置文件来解决这个问题

# 进入到Kibana容器内部
docker exec -it kibana /bin/bash
# 进入配置文件夹
cd config
# 修改kibana.yml配置文件
vi kibana.yml

如下图所示,需要修改elasticsearch.hosts这项配置,将访问的IP修改为elasticsearch服务地址

在这里插入图片描述

5.3.使用

在这里插入图片描述

6.ElasticSearch的核心概念

Elasticsearch是面向文档的非关系型数据库。
关系型数据库和Elasticsearch的客观比较如下:

关系型数据库 Elasticsearch
数据库(database) 索引(indices)
表(table) 类型(types,即将被弃用)
行数据(row) 文档(documents)
字段(columns) 字段(fields)

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

ES物理设计

elasticsearch在后台吧每个索引分成多个分片,每份分片可以在集群中的不同服务器间迁移

逻辑设计

一个索引类型中,包含多个文档,比如说文档1,文档2.当我们搜索一篇文档时,可以通过这样的一个顺序找到它:
索引 》类型 》文档ID 》通过这个组合我们就能检索到某个具体的文档。

注意:ID不必是整数,实际上它是个字符串

6.1.文档

Elasticserach是面向文档的,那么就意味着索引和搜索数据的最小单位是文档,Elasticsearch,文档有几个重要的属性:

  • 自我包含:一篇文档同时包含字段和对应的值,也就是同时包含key:value
  • 可以是层次型的,一个文档中包含子文档,浮渣的逻辑实体就是这么来的
  • 灵活的结构,文档不依赖预先模式。在关系型数据库中,要提前定义字段才能使用,在elasticsearch中,对于字段是非常灵活的。有时候可以忽略某些字段,或者动态的添加一个新的字段

尽管我们可以随意的增加或者忽略某个字段,但是每个字段的类型非常重要。比如一个年龄字段类型,可以是字符串也可以是整数类型。因为Elasticsearch会保存字段和类型之间的映射及其他的设置。这种映射具体到每一个映射的每种类型,这也是为什么在elasticsearch会保存字段和类型之间的映射及其他的设置。这种映射具体到每个映射的每种类型,这也是为什么在elasticsearch中类型有时候也成为映射类型

6.2.类型

类型是文档的逻辑容器,就像关系型数据库一样,表格是行的容器。类型中对于字段的定义称为映射,比如name映射为字符串类型。我们说文档是无模式的,它不需要拥有映射中所定义的所有字段,比如新增一个字段,那么elasticsearch会自动将新字段加入映射,但是elasticsearch也不知道这个字段是什么类型,于是就会对此进行猜测。如果这个值是18,那么elasticsearch就会认为它是一个整数类型。但是elasticsearch也可能猜不对,所有最安全的方式就是提前的钱定义好所需要的映射。

6.3.索引

索引就是映射关系的容器,elasticsearch中的索引是一个非常大的文档集合。索引存储了映射类型的字段和其他设置,然后它们会被存储到各个分片上。

6.4.物理设计:节点和分片是如何工作的

一个集群至少有一个节点,而一个节点就是一个elasticsearch进程,节点可以有多个索引(默认的)。如果您创建索引,那么索引将会有5个分片(primary shard,又称主分片)构成的,每一个主分片会有一个副本(replica shard,又称复制分片)

在这里插入图片描述

在这里插入图片描述

如上图为一个3节点的集群,可以看到主分片对于的复制分片都不会在同一个节点内,这样有利于某个节点意外down机,数据也不会丢失。实际上,一个分片是一个Lucene索引,一个包含到排索引的文件目录,倒排索引的结构使得elasticsearch在不扫描全部文档的情况下,就能告诉你那些文档包含特定的关键字

6.5.倒排索引

Elasticsearch使用的是一种称为倒排索引的结构,采用Lucene倒排索引做为底层。这种结构适用于快速的全文搜索,一个索引由文档中所有不重复的列表构成,对于每一个词,都有一个它的文档列表。例如,现在有两个文档,每个文档包含如下内容:

study every day,good good up to forever # 文档1包含的内容
To forever,study every day,good good up # 文档2包含的内容

为了创建倒排索引,我们首先要每个文档拆分成独立的词(或者称为词条或者tokens),然后创建一个包含所有不重复的词条的排序列表,然后列出每个词条出现在那个文档中

Term doc_1 doc_2
study V X
To X V
every V V
forever V V
day V V
study X V
good V V
every V V
to V X
up V V

现在,我们来搜索一个 to forever,只需要查看包含每个词条的文档

Term doc_1 doc_2
to V X
forever V V
total 2 1

两个文档都匹配,但是第一个文档比第二个匹配程度高。如果没有别的条件,现在,同时包含这两个包含关键字的文档将被返回

倒排索引理解示例:

比如我们通过博客的标签来搜索博客文章,详细如下:

博客文章ID 标签
1 python
2 python
3 Linux python
4 Linux

那么倒排索引列表就是这样的一个结构

标签 博客文章ID
python 1,2,3
Linux 3,4

如果要搜索含有python标签的文章,那相对于查找所有原始数据而言,查找倒排索引的数据将会快很多。只需要查看标签这一栏,然后取到相关的文章ID即可,完全过滤无关的文档。

elasticsearch的索引和Lucene的索引对比

在elasticsearch中,索引这个词被频繁使用,这就是术语的使用,在elasticsearch中,索引被分为多个分片,每份是一个Lucene的索引。所以一个elasticsearch索引是由多个Lucene索引组成的。

7.IK分词器

什么是IK分词器?

分词:即把一段中文或者别的划分成一个个的关键字,我们在搜索的时候会把自己的信息进行分词,会把数据库中的或者索引库中的数据进行分词,然后进行一个匹配操作。默认的中文分词是将每一个字看成一个词。

IK提供两个分词算法:ik_smartik_max_word,其中ik_smart为最少切分,ik_max_word为最细粒度划分!

7.1.安装IK分词器

# 进入到elasticsearch容器里面
docker exec -it es /bin/bash
# 进入到插件目录
cd /usr/share/elasticsearch/plugins
# 下载IK分词器插件(我这里的版本是对应的es版本)
elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.6.1/elasticsearch-analysis-ik-7.6.1.zip
# 下载好后退出es容器,重启es容器

在这里插入图片描述

7.2.IK分词器使用

使用Kibana测试
在这里插入图片描述

7.3.分词器扩展字典配置

IK分词器会根据算法去拆分,拆分的依据是根据它默认的一个词库。可能有些自己想连起来的词IK默认的词库达不到要求,此时我们就可以自己去定义一些词库字典。

首先第一步我们先要找到在哪里配置:

# 进入es容器
docker exec -it es /bin/bash
# 进入插件目录
cd /usr/share/elasticsearch/plugins
# 进入IK分词器插件
cd analysis-ik/
# 进入分词器配置目录
cd config/
# 查看分词配置文件
cat IKAnalyzer.cfg.xml

详细操作如下图

在这里插入图片描述

现在我们可以自己去创建一个dic字典

# 创建一个自定义分词字典文件
touch myTest.dic

先不着急编写内容,可以先通过Kibana来验证一下。
在kibana中对"text":"good man"进行默认的内容拆分测试,详细如下图所示:

在这里插入图片描述

现在我想得到的分词中有一项为 good ma,现在可以编辑myTest.dic文件在文件中输入内容:代码ok
配置:
在这里插入图片描述

重启elasticsearch和kibana

8.Rest风格说明

8.1.简单介绍

Rest是一种软件风格,而不是一种标准,指数一个一组设计原理和约束条件。它主要用于客户端和服务器交互类的软件。给予这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

基本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 查询所有数据

8.2.演示事例

8.2.1.索引相关操作

创建索引

PUT /test1/type1/1
{
    
	"name":"jimmy",
  "age":"21"
}

在这里插入图片描述

ES中的字段类型

  • 字符串类型

    text(text类型会被分词器解析/拆分)、keyword(keyword类型不会被分词器解析)

  • 数值类型

    long、integer、short、byte、double、float、half、float、scaled、float

  • 日期类型

    date

  • 布尔类型

    boolean

  • 二进制类型

    binary

  • 等等…

创建规则:创建索引时指定字段的类型。

PUT /test2
{
    
  "mappings": {
    
    "properties": {
    
      "name":{
    
        "type":"text"
      },
      "age":{
    
        "type":"integer"
      }
    }
  }
}

获取test2索引的规则信息,通过GET请求获取

GET /test2

在这里插入图片描述

获取test1索引的规则信息(创建test1索引时没有设置字段类型规则,es会帮我们自动配置)

# 查询索引信息
GET /test1

在这里插入图片描述

拓展命令

# 获取ES健康值
GET _cat/health
# 查看ES的所有信息
GET _cat/indices?v

在这里插入图片描述
在这里插入图片描述

修改文档
修改文档有两种方式:

  • 1、通过再次提交去覆盖原有的值
PUT /test1/type1/1
{
     
  "name":"邪恶的张三",
  "age":23
}

在这里插入图片描述

  • 2、通过POST:localhost:9200/索引名称/类型名称/文档ID/_update的方式去更新文档中指定字段的值。灵活性更高
POST /test1/type1/1/_update
{
     
  "doc":{
     
    "name":"好人张三"
  }
}

在这里插入图片描述

删除索引

DELETE test1
8.2.2.查询
# 查询准备数据
# 1.创建索引及字段映射规则
PUT /search_data_list
{
    
  "mappings": {
    
    "properties": {
    
      "name":{
    "type": "text"},
      "age":{
    "type":"integer"},
      "birthday":{
    "type":"date"},
      "tags":{
    "type": "text"}
    }
  }
}
# 2.添加数据
PUT /search_data_list/_doc/1
{
    
  "name":"张三",
  "age":23,
  "birthday":"2021-04-13",
  "tags":["抽烟","喝酒","汤头"]
}

PUT /search_data_list/_doc/2
{
    
  "name":"李四",
  "age":24,
  "birthday":"2021-04-13",
  "tags":["抽烟","喝酒","汤头"]
}

PUT /search_data_list/_doc/3
{
    
  "name":"王五",
  "age":25,
  "birthday":"2021-04-13",
  "tags":["抽烟","喝酒","汤头"]
}

PUT /search_data_list/_doc/4
{
    
  "name":"王五均",
  "age":26,
  "birthday":"2021-04-13",
  "tags":["抽烟","喝酒","汤头"]
}

# 简单查询
# 1.查看索引结构
GET search_data_list
# 2.查看_doc文档下文档ID为2的数据
GET search_data_list/_doc/2
# 3.查询 name=王五 的数据,右边查询出来的_score字段表示数据匹配度,值越大匹配度越高
GET search_data_list/_doc/_search?q=name:王五

# 复杂查询
# query 查询条件结果集
# match 相当于mysql中的and
# _source 结果过滤只取需要的字段
GET search_data_list/_doc/_search
{
    
  "query":{
    
    "match": {
    
      "name": "王五"
    }
  },
  "_source":["name","desc"]
}
# 排序
GET search_data_list/_doc/_search
{
    
  "query":{
    
    "match": {
    
      "name": "王五"
    }
  },
  "sort":{
    
    "age":{
    
      "order":"asc"
    }
  }
}
# 分页
# from 起始值(从0开始)
# size 偏移量
GET search_data_list/_doc/_search
{
    
  "query":{
    
    "match": {
    
      "name": "王五"
    }
  },
  "sort":{
    
    "age":{
    
      "order":"asc"
    }
  },
  "from":0,
  "size":1
}
# 多条件查询
# match > and
# should > or
# must_not > !=
GET search_data_list/_doc/_search
{
    
  "query":{
    
    "bool":{
    
      "must_not":[
        {
    
          "match":{
    "name":"张三"}
        },
        {
    
          "match":{
    "age":23}
        }
      ]
    }
  }
}

# 过滤器
# 使用 filter 对数据进行过滤
# gt大于 gte大于等于 lt小于 lte小于等于
GET search_data_list/_doc/_search
{
    
  "query":{
    
   "bool":{
    
     "must":[
        {
    
          "match":{
    "name":"王五"}
        }  
     ],
    "filter":{
    
      "range":{
    
        "age":{
    
          "lt":26
          }
        }
      }
    }
  }
}

# 精确查询,通过倒排索引指定的词条进行精确查找
# term 直接查询精确的,match 会使用分词器解析(先分析文档,然后再通过分析文档进行查询)
GET search_data_list/_doc/_search
{
    
  "query":{
    
    "term":{
    
      "name":"王"
    }
  }
}

# 多条件精确查询
GET search_data_list/_doc/_search
{
    
  "query":{
    
    "bool":{
    
      "should":[
        {
    
          "term":{
    "age":13}
        },
        {
    
          "term":{
    "age":25}
        }
      ]
  }
}
  
# 高亮查询
GET search_data_list/_doc/_search
{
    
  "query":{
    
    "match":{
    
      "name":"张三"
    }
  },
  "highlight":{
    
    "fields":{
    
      "name":{
    }
    }
  }
}

# 自定义高亮显示
GET search_data_list/_doc/_search
{
    
  "query":{
    
    "match":{
    
      "name":"张三"
    }
  },
  "highlight":{
    
    "pre_tags":"<p>",
    "post_tags":"</p>",
    "fields":{
    
      "name":{
    }
    }
  }
}

9.SpringBoot整合ElasticSearch实现CRUD操作

9.1.导入依赖

导入依赖的时候需要注意,es客户端的版本需要和本地es服务的版本一致。
SpringBoot整合的es默认时使用父工程的版本,所以我们在编写代码前需要去看一下高级的Rest风格的es客户端版本。详细操作如下图:
在这里插入图片描述

我本地的es服务的版本是7.6.1的,这里依赖父工程的版本是7.6.2。保险请见我需要调整一下es客户端的版本

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

<!--EsClient的版本要和ES的版本一致-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

到这一步就可以开始写代码了…

9.2.构建ES客户端实例

package com.scholartang.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;

/**
 * @Author ScholarTang
 * @Date 2021/4/13 2:02 下午
 * @Desc ES 配置类
 */
@Configuration
public class ElasticSearchConfig {
    

    /**
     * 构建一个高级的Rest风格的es客户端实例
     * 一个RestHighLevelClient实例需要一个REST低级别的客户端生成器 来构建如下
     * @return
     */
    @Bean
    public RestHighLevelClient restHighLevelClient(){
    
        return new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
    }
}

9.3.索引相关操作API测试

package com.scholartang;

import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;

/**
 * es 7.6.1 高级客户端测试API(索引相关)
 */
@Slf4j
@SpringBootTest
class EsDemoApplicationTests {
    

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    /**
     * 创建索引
     */
    @Test
    void testCreateIndex() throws IOException {
    
        //创建索引请求
        CreateIndexRequest createIndexRequest = new CreateIndexRequest("create_index_01");
        //客户端执行请求
        restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
    }

    /**
     * 获取索引
     */
    @Test
    public void testGetIndex() throws IOException {
    
        //创建获取索引请求
        GetIndexRequest getIndexRequest = new GetIndexRequest("create_index_01");
        //客户端执行请求
        boolean exists = restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
        log.info("索引" + (exists ? "存在" : "不存在"));
    }

    /**
     * 删除索引
     */
    @Test
    public void testDeleteIndex() throws IOException {
    
        //创建删除索引请求
        DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("create_index_01");
        //客户端执行请求
        restHighLevelClient.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
    }
}

9.4.文档先关操作API测试

package com.scholartang;

import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;

/**
 * es 7.6.1 高级客户端测试API(文档相关)
 */
@Slf4j
@SpringBootTest
class EsDemoApplicationTests {
    
  @Autowired
  private RestHighLevelClient restHighLevelClient;
  
   /** 添加文档 */
  @Test
  public void testAddDocument() throws IOException {
    
    // 创建一个索引请求
    IndexRequest indexRequest = new IndexRequest("create_index_01");
    // 文档ID
    indexRequest.id("1");
    // 设置请求超时时间
    indexRequest.timeout(TimeValue.timeValueMillis(1));
    // 也可以这么写 indexRequest.timeout("60s");
    // 设置文档数据
    indexRequest.source(JSON.toJSONString(new User(1, "张三", "男", 23)), XContentType.JSON);
    // 客户端发送添加文档请求
    IndexResponse index = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
    log.info("IndexResponse:{}", JSON.toJSONString(index));
  }

  /** 获取文档信息 */
  @Test
  public void testGetDocument() throws IOException {
    
    // 创建一个获取请求 get /index/_doc/documentId
    GetRequest getRequest = new GetRequest("create_index_01", "5");
    GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
    if (getResponse.isExists()) {
    
      String source = getResponse.getSourceAsString();
      log.info("source:{}", source);
    }
  }

  /** 更新文档信息 */
  @Test
  public void testUpdateDocument() throws IOException {
    
    // 创建一个更新请求
    UpdateRequest updateRequest = new UpdateRequest("create_index_01", "1");
    updateRequest.timeout("60s");
    updateRequest.doc(JSON.toJSONString(new User(2, "kuang", "女", 23)), XContentType.JSON);
    UpdateResponse updateResponse =
        restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
    log.info("updateStatus:{}", updateResponse.status());
  }

  /** 删除文档 */
  @Test
  public void testDeleteDocument() throws IOException {
    
    // 创建一个删除请求
    DeleteRequest deleteRequest = new DeleteRequest("create_index_01", "1");
    deleteRequest.timeout("60s");
    DeleteResponse deleteResponse =
        restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
    log.info("deleteResponse:{}", deleteResponse.status());
  }

  /** 批量插入文档 */
  @Test
  public void testBathAddDocument() throws IOException {
    
    BulkRequest bulkRequest = new BulkRequest();
    bulkRequest.timeout("60s");
    ArrayList<User> users = new ArrayList<>();
    Collections.addAll(
        users,
        new User(1, "kuang1", "女", 23),
        new User(2, "kuang2", "女", 23),
        new User(3, "kuang3", "女", 23),
        new User(4, "kuang4", "女", 23));
    for (int i = 0; i < users.size(); i++) {
    
      bulkRequest.add(
          // 批量的更新操作和删除操作,在这里修改请求方式即可
          new IndexRequest("create_index_01")
              .id((i + 1) + "")
              .source(JSON.toJSONString(users.get(i)), XContentType.JSON));
    }
    BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
    // 操作是否失败,返回false则为成功
    log.info("bulkResponseStatus:{}", bulkResponse.isFragment());
  }

  /** 批量查询操作 */
  @Test
  public void testBathGetDocument() throws IOException {
    
    // 创建批量查询请求
    SearchRequest searchRequest = new SearchRequest("create_index_01");
    // 构建查询条件
    SearchSourceBuilder builder = new SearchSourceBuilder();
    // QueryBuilders 条件工具类
    // termQuery 精确查询
    TermQueryBuilder termQuery = QueryBuilders.termQuery("name", "kuang1");
    // matchAllQuery 匹配所有
    // MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
    // builder.query(termQuery);
    // 根据文档ID批量查询
    IdsQueryBuilder idsQueryBuilder = new IdsQueryBuilder().addIds("1", "2", "3", "100");
    builder.query(idsQueryBuilder);
    // 设置请求超时时间
    builder.timeout(new TimeValue(60, TimeUnit.SECONDS));
    searchRequest.source(builder);
    // 客户端发起请求
    SearchResponse searchResponse =
        restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    RestStatus status = searchResponse.status();
    if ("ok".equalsIgnoreCase(status.toString())) {
    
      // 所有的结果都是在 SearchHits 里面
      List<Map> maps = new ArrayList<>();
      SearchHits responseHits = searchResponse.getHits();
      SearchHit[] hits = responseHits.getHits();
      for (int i = 0; i < hits.length; i++) {
    
        maps.add(hits[i].getSourceAsMap());
      }
      log.info(JSON.toJSONString(maps));
    }
  }
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/ScholarTang/article/details/115869856

智能推荐

python高手之路 pdf百度云,python高手到什么水平-程序员宅基地

文章浏览阅读567次,点赞9次,收藏18次。authors : '【美】丹尼尔·戈尔曼\\n【美】理查德·博亚特兹\\n【美】安妮·麦基'authors : '【美】乔治·阿克洛夫\\n【美】罗伯特·席勒'authors : '【英】蒂姆·维卡利,萨菲娜·德福奇 等'title : '大谋小计五十年:诸葛亮传(全五册)',title : '周浩晖推理悬疑经典集(共10册)',authors : '【英】吉尔伯特·基思·切斯特顿'title : '春秋战国真有趣(全六册)',authors : '【美】马里奥·普佐'

当前顶点状态和顶点数组——OpenGL ES Common/Common-Lite 规范(版本 1.1.12)_查看当前顶点在哪个顶点组-程序员宅基地

文章浏览阅读1.4k次。当前顶点状态当一个顶点数组被定义,但是数据还不可用时,当前值常用于联合顶点辅助的数据。当前值可能在任何时候被独占命令改变。使用以下的命令可设置当前的RGBA颜色值。void Color4{xf}(T red, T green, T blue, T alpha);void Color4ub(ubyte red, ubyte green, ubyte blue, uby_查看当前顶点在哪个顶点组

用JAVAFX做一个简单的桌面宠物(四)-程序员宅基地

文章浏览阅读603次。(完结篇)实现自动行走的功能(Move类)类成员与构造函数private long time;private ImageView imageView;private int direID; double x; double maxx; double width; Rectangle2D screenBounds = Screen.getPrimary().getVisualBounds(); Stage stage;private EventListener lis

Anaconda详细安装及环境变量配置(图文)_anaconda环境变量-程序员宅基地

文章浏览阅读3.9w次,点赞39次,收藏182次。AnacondaAnaconda指的是一个开源的Python发行版本,其包含了conda、Python等180多个科学包及其依赖项。因为包含了大量的科学包,Anaconda的下载文件比较大(约531 MB),如果只需要某些包,或者需要节省带宽或存储空间,也可以使用Miniconda这个较小的发行版(仅包含conda和Python)。Conda是一个开源的包、环境管理器,可以用于在同一个机器上安装不同版本的软件包及其依赖,并能够在不同的环境之间切换。Anaconda包括Conda、Pyth..._anaconda环境变量

Python 之 Pandas (一)介绍_s = pd.series(['湖北', '浙江', '广东'])-程序员宅基地

文章浏览阅读601次。代码:import pandas as pdimport numpy as npprint("生成序列")s = pd.Series([1, 3, 6, np.nan, 44, 1])print(s)dates = pd.date_range('20160101', periods=6)print(dates)运行结果:生成序列0 1.01 3.02 6..._s = pd.series(['湖北', '浙江', '广东'])

java icon动态变换_Android实现APP安装后动态更换Icon和名称-程序员宅基地

文章浏览阅读200次。最近看到手机自带的时钟App可以实时的修改图标样式,就觉得很神奇。考虑到我自己要做的日记App可能也需要这样的功能,于是研究了一下,目前初步实现了修改图标及点击后进入不同Activity的功能,代码比较简单,点击这里download ZIP。简单效果图:原来调用修改方法:代码很简单,就2个部分:1.修改manifest文件:package="sxkeji.net.aliasdemo" >an..._android app 更换电子门牌 demo

随便推点

pandas 时间戳转时间保留北京时间日期(to_datetime )_pandas to_datetime 北京时间-程序员宅基地

文章浏览阅读8.8k次,点赞4次,收藏8次。``` user_id create_time0 38441 15410016021 38442 15410016642 38443 15410017443 38444 15410019264 38445 15410020125 38446 15410024136 38447 15410..._pandas to_datetime 北京时间

mysql 8.0 创建新的数据库、用户并授权,以及相关查看并删除操作_mysql8.0 添加创建数据库权限-程序员宅基地

文章浏览阅读1.6k次。一、创建数据库mysql> create database news character set utf8;Query OK, 0 rows affected (0.09 sec)二、创建用户mysql> create user ‘news’@‘39.15.16.14’ identified by ‘123news’;Query OK, 0 rows affected (0.09 sec)三、授权用户mysql> grant all privileges on news.* _mysql8.0 添加创建数据库权限

SonarQube学习笔记二:Sonar插件安装和API调用示例_sonar-pdf-plugin-程序员宅基地

文章浏览阅读1.9k次。本文主要内容是sonarqube安装插件实现功能扩展,也对sonarqube的API功能进行了可用性确认。_sonar-pdf-plugin

vue使用fullCalendar插件(类似日程表)_vue 行程插件-程序员宅基地

文章浏览阅读6.4w次,点赞6次,收藏44次。基本操作传送门显示效果图添加效果图代码:<template> <div style="width:90%;margin: 20px auto;"> <!-- ref 用来拿到这个日历对象 defaultView 默认以月份方式显示 locale 语言 header 头部的按钮 buttonText 头部按钮的文字 plugins 插件 wee......_vue 行程插件

关于layout_centerHorizontal、layout_gravity、gravity的区别-程序员宅基地

文章浏览阅读1.2w次,点赞5次,收藏8次。layout_centerHorizontal是相对于RelativeLayout的布局属性如果设置为true,就将该控价设置在相对于父控件水平居中的位置layout_gravity针对LinearLayout的一种控件对齐方式,可以把值设置成下列值:center_vertical、center_horizontal、center等等gravity控制控件内文字的对齐方式举个栗子:在写一个简单的

python循环嵌套_python循环j和i每循环9个一分行-程序员宅基地

文章浏览阅读1.9k次。#一,循环嵌套##1,双for循环嵌套"""外层循环每循环一次,内层循环循环所有次,内层循环体执行就是内外层循环次数的乘积for i in "范围": #循环9次 for j in "范围":# 循环9次 "循环体""""for x in range(3): for y in range(3): print("%d %d" % (x, y))#例2打印99 乘法表for i in range(1, 10):# 循环打印数字0到9 for_python循环j和i每循环9个一分行

推荐文章

热门文章

相关标签