ElasticSearch入门实战介绍

全文检索

什么是全文检索

全文检索是一种通过对文本内容进行全面索引和搜索的技术。

设想一个全文检索的场景,比如搜索Elasticsearch原理:

在这里插入图片描述

总结: 根据提供的信息,返回与之关键字相关的所有内容

思考:用传统关系型数据库实现有什么问题?

select * from t_blog where content like "%elasticsearch原理%"

这种需要遍历所有的记录进行匹配,如果数据量比较庞大的话,不但查询效率低,而且搜索结果不符合我们搜索时的期望。

全文检索的原理

  1. 首先需要对文本数据进行处理,比如:分词,过滤停用词等。
  2. 对分好的词建立倒排索引,索引会记录每个单词在文档中的 位置信息以及其他相关的元数据,如词频、权重等。
  3. 当用户发起搜索请求时,搜索引擎会根据用户提供的关键词 或短语,在建立好的索引中查找匹配的文档

什么是倒排索引?

  • 索引一般分为正排索引与倒排索引两种。

  • mysql库索引,就是正排索引,通过表字段依次匹配。

  • 倒排索引是根据单词或短语建立的索引结构,需要对文档进行分词处理,然后记录每个单词在哪些文档中出现,以及出现的位置信息,这样能够快速定位文档,提高搜索效率。

我们在创建文章的时候,建立一个关键词与文章的对应关系表,也可以称之为倒排索引。如下图所示:

关键词文章id是否命中
elasticsearch1,2✔️
原理1,2,3,4✔️
java3
设计模式2

ElasticSearch介绍

官网地址
下载地址

ElasticSearch(简称ES)是一个开源的分布式搜索和数据分析引擎,是用Java开发并且是当前最流行的开源的企业级搜索引擎,能够达到近实时搜索,它专门设计用于处理大规模的文本数据和实现高性能的全文检索。

以下是一些 Elasticsearch 的特点和优势:

  • 分布式架构:Elasticsearch 是一个分布式系统,可以轻松地 水平扩展处理大规模的数据集和高并发的查询请求。

  • 全文检索功能:Elasticsearch 提供了强大的全文检索功能, 包括分词、词项查询、模糊匹配、多字段搜索等,并支持 丰富的查询语法和过滤器。

  • 多语言支持:Elasticsearch 支持多种语言的分词器和语言 处理器,可以很好地处理不同语言的文本数据。

  • 高性能:Elasticsearch 使用倒排索引和缓存等技术,具有 快速的搜索速度和高效的查询性能。

  • 实时性:Elasticsearch 支持实时索引和搜索,可以几乎实时地将文档添加到索引中,并立即可见。

  • 易用性:Elasticsearch 提供了简单易用的 RESTful API,方便进行索引管理、查询操作和数据分析。

搜索引擎排名:

在这里插入图片描述

参考网站:https://db-engines.com/en/ranking/search+engine

ElasticSearch应用场景

只要用到搜索的场景,ES几乎都可以是最好的选择。 除了搜索之外,还被广泛运用在大数据分析,日志分析,
指标监控,信息安全等多个领域,可以帮助你对海量数据 进行探索,监控等

技术选型对比

ElasticsearchSolrMongoDBMySQL
DB类型搜索引擎搜索引擎文档数据库关系型数据库
基于何种框架开发LuceneLucene
基于何种开发语言JavaJavaC++C、C++
数据结构FST、Hash等B+ Trees
数据格式JsonJson/XML/CSVJsonRow
分布式支持原生支持支持原生支持不支持
数据分区方案分片分片分片分库分表
业务系统类型OLAPOLAPOLTPOLTP
事务支持不支持不支持多文档ACID事务支持
数据量级PB级TB级~PB级PB级单库3000万
一致性策略最终一致性最终一致性最终一致性即时一致性即时一致性
擅长领域海量数据全文检索大数据聚合分析大数据全文检索海量数据CRUD
劣势不支持事务写入实时性低海量数据的性能不如ES随着数据量的不断增大,稳定性低于ES弱事务支持不支持join查询大数据全文搜索性能低
查询性能★★★★★★★★★★★★★★★★★
写入性能★★★★★★★★★★★

总结:Mysql存储数据量比较少,需要考虑分库分表,MongoDB更适合需要高效读写和大规模数据存储的应用,‌而Elasticsearch则更适合需要进行复杂搜索和分析的应用场景

ElasticSearch环境搭建

安装ElasticSearch

安装文档
https://www.elastic.co/guide/en/elasticsearch/reference/8.14/targz.html
下载地址
https://www.elastic.co/cn/downloads/past-releases#elasticsearch

windows安装ElasticSearch

下载ElasticSearch

windows
https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.14.2-windows-x86_64.zip

ElasticSearch文件目录结构

目录描述
bin脚本文件,包括启动elasticsearch,安装插件,运行统计数据等
config配置文件目录,如elasticsearch配置、角色配置、jvm配置等。
jdk7.x 以后特有,自带的 java 环境,8.x版本自带jdk 17
data默认的数据存放目录,包含节点、分片、索引、文档的所有数据,生产环境需要修改。
libelasticsearch依赖的Java类库
logs默认的日志文件存储路径,生产环境需要修改。
modules包含所有的Elasticsearch模块,如Cluster、Discovery、Indices等。
plugins已安装插件目录

配置JDK环境

  • ES比较耗内存,建议虚拟机4G或以上内存,jvm1g以上的内存分配
  • 运行Elasticsearch,需安装并配置JDK。 各个版本对Java的依赖地址
    https://www.elastic.co/cn/support/matrix#matrix_jvm
  • 7.0开始,内置了Java环境。ES的JDK环境变量生效的优先级配置顺序 ES_JAVA_HOME>JAVA_HOME>ES_HOME
  • ES_JAVA_HOME:这个环境变量用于指定Elasticsearch使用的Java运行时环境的路径。在启动Elasticsearch时,它会检查ES_JAVA_HOME环境变量并使用其中的Java路径。
  • ES_HOME:这个环境变量指定Elasticsearch的安装路径。它用于定位Elasticsearch的配置文件、插件和其他相关资源。设置ES_HOME环境变量可以让您在命令行中更方便地访问Elasticsearch的目录结构和文件。

温馨提示:

  1. 初学者建议直接安装windows版本elasticSearch。
  2. 在windows下,需要设置ES_JAVA_HOME和ES_HOME环境变量。
  3. 安装包解压后就可以进入bin目录,直接运行elasticsearch.bat。
  4. 浏览器中就可以访问:http://localhost:9200/ 了

centos7安装ElasticSearch

下载ElasticSearch

linux
https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.14.3-linux-x86_64.tar.gz

解压

tar -zxvf elasticsearch-8.14.3-linux-x86_64.tar.gz

注意:es默认不能用root用户启动,建议先为elasticsearch创建用户。

  1. 为elaticsearch创建用户并赋予相应权限
  2. adduser es
  3. passwd es
  4. chown -R es:es elasticsearch-17.3

切换es用户

su es

配置JDK环境

  1. linux 进入用户主目录,比如/home/es目录下,设置用户级别的环境变量
  2. vim .bash_profile
  3. 设置ES_JAVA_HOME和ES_HOME的路径
  4. export ES_JAVA_HOME=/home/es/elasticsearch-8.14.3/jdk
  5. export ES_HOME=/home/es/elasticsearch-8.14.3
  6. #执行以下命令使配置生效
  7. source .bash_profile

修改配置

单机模式启动配置
vim elasticsearch.yml
#开启远程访问
network.host: 0.0.0.0
#单节点模式
discovery.type: single-node
默认为true,启用节点上ES的XPACK安全功能,相当于总开关
xpack.security.enabled: false
配置好以后直接./bin/elasticsearch就可以运行了。

集群模式启动配置
vim elasticsearch.yml
#开启远程访问
network.host: 0.0.0.0
默认为true,启用节点上ES的XPACK安全功能,相当于总开关
xpack.security.enabled: false

修改jvm参数配置
vim jvm.options
#修改参数
-Xms1g
-Xmx1g
配置的建议
1. Xms和Xms设置成—样
2. Xmx不要超过机器内存的50%
3. 不要超过30GB
配置好以后直接./bin/elasticsearch就可以运行了。

启动方式

#非root用户启动
窗口启动
bin/elasticsearch
后台启动
./bin/elasticsearch -d

启动ES服务常见错误解决方案

  1. max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536]
    ES因为需要大量的创建索引文件,需要大量的打开系统的文件,所以我们需要解除linux系统当中打开
    文件最大数目的限制,不然ES启动就会抛错。
 #切换到root用户
 vim /etc/security/limits.conf
 
 末尾添加如下配置:
 	* soft nofile 65536 
 	* hard nofile 65536 
 	* soft nproc 4096 
 	* hard nproc 4096
  1. max number of threads [1024] for user [es] is too low, increase to at least [4096]
    无法创建本地线程问题,用户最大可创建线程数太小
 vim /etc/security/limits.d/20-nproc.conf
 
 改为如下配置:
 	* soft nproc 4096
  1. max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
    最大虚拟内存太小,调大系统的虚拟内存
 vim /etc/sysctl.conf
 
 追加以下内容:
 vm.max_map_count=262144
 
 保存退出之后执行如下命令:
 sysctl -p
  1. the default discovery settings are unsuitable for production use; at least one of
    [discovery.seed_hosts, discovery.seed_providers, cluster.initial_master_nodes] must be configured
    缺少默认配置,至少需要配置
    discovery.seed_hosts
    discovery.seed_providers
    cluster.initial_master_nodes
    中的一个参数.
    discovery.seed_hosts: 集群主机列表
    discovery.seed_providers: 基于配置文件配置集群主机列表
    cluster.initial_master_nodes: 启动时初始化的参与选主的node,生产环境必填
 vim config/elasticsearch.yml
 
 #添加配置
 discovery.seed_hosts: ["127.0.0.1"]
 cluster.initial_master_nodes: ["node-1"]

 #或者指定配置单节点(集群单节点)
 discovery.type: single-node

客户端Kibana安装

Kibana是一个开源分析和可视化平台,就是为了与Elasticsearch协同工作
参考文档:https://www.elastic.co/guide/en/kibana/8.14/get-started.html

下载地址

Windows:https://artifacts.elastic.co/downloads/kibana/kibana-8.14.3-windows-x86_64.zip

Linux:https://artifacts.elastic.co/downloads/kibana/kibana-8.14.3-linux-x86_64.tar.gz

运行kibana

windows
运行Kibana
直接执行kibana.bat

Linux
注意:kibana也需要非root用户启动
bin/kibana
后台启动
nohup bin/kibana &
查询kibana进程
netstat -tunlp | grep 5601
访问Kibana
http://localhost:5601/app/dev_tools#/console

注意:kibana 使用ps -ef|grep kibana是查不到进程的,因为其实运行在node里面。但是我们也不能关闭所有node里面的软件,所以我们需要查询kibana监听端口5601的进程,所以需要如下操作:

[es@ ~]$ netstat -tunlp|grep 5601
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 192.168.1.100:5601      0.0.0.0:*               LISTEN      89671/./bin/../node 
[es@ ~]$ kill -9 89671

Elasticsearch安装分词插件

在线安装analysis-icu分词插件

查看已安装插件
bin/elasticsearch-plugin list
安装插件
bin/elasticsearch-plugin install analysis-icu
删除插件
bin/elasticsearch-plugin remove analysis-icu

注意:安装和删除完插件后,需要重启ES服务才能生效。

离线安装ik中文分词插件

下载地址:https://release.infinilabs.com/analysis-ik/stable/
解压,然后手动上传到elasticsearch的plugins目
录,然后重启ES实例就可以了。

注意:es版本需要与ik一致

不一致怎么办

我的ES版本是8.14.3
由于ik没有8.14.3这个版本我使用的8.14.2版本
导致启动报版本不匹配的错误
所以我们需要修改他下面的
plugin-descriptor.properties
这个文件
把所有的8.14.2改为8.14.3然后就可以运行了

测试分词效果

以上介绍2中分词器安装,es还默认支持Standard Analyzer 分词器 这种分词器对中文不太友好,单个字切个,以下是各个分词器效果展示:

  1. 默认分词器
    在这里插入图片描述
  1. analysis-icu分词器
    在这里插入图片描述
  1. ik_smart为最少,粗粒度切分
    在这里插入图片描述
  1. ik_max_word为最细粒度划分
    在这里插入图片描述

附上测试实例信息

# 默认分词器 Standard Analyzer

POST _analyze
{
  "analyzer":"standard",
  "text":"今天天气很好,很适合出去玩"
}

# analysis-icu 分词器
POST _analyze
{
  "analyzer":"icu_analyzer",
  "text":"今天天气很好,很适合出去玩"
}
# ik ik_smart为最少切分
POST _analyze
{
 "analyzer":"ik_smart",
 "text":"今天天气很好,很适合出去玩"
}
# ik ik_max_word为最细粒度划分
POST _analyze
{
 "analyzer":"ik_max_word",
 "text":"今天天气很好,很适合出去玩"
}

在ES中支持中文分词器,推荐使用的就是 IK分词器

ElasticSearch核心概念

节点:Node

一个节点就是一个Elasticsearch的实例,可以理解为一个 ES 的进程。

角色:Roles

ES的角色分类:

  • 主节点(active master):一般指活跃的主节点,一个集群中只能有一个,主要作用是对集群的管理
  • 候选节点(master-eligible):当主节点发生故障时,参与选举,也就是主节点的替代节点
  • 数据节点(data node):数据节点保存包含已编入索引的文档的分片。数据节点处理数据相关操作,如CRUD、搜索和聚合。这些操作是 I/O 密集型、内存密集型和 CPU 密集型的。监控这些资源并在它们过载时添加更多数据节点非常重要。
  • 预处理节点(ingest node):预处理节点有点类似于消息管道,常用于一些数据写入之前预处理操作。

注意:一般用于集群中,node.roles属性进行角色分配,如果 node.roles 为缺省配置,那么当前节点具备所有角色

索引:Index

索引在 ES 中所表述的含义和 MySQL 中的索引完全不同,在 MySQL 中索引指的是加速数据查询的一种特殊的数据结构。
在 ES 中,索引表述的含义可以想象成 MySQL 中的表,注意这里只是类比去理解,索引并不等于表

es 8.15.3版本索引结构如下
在这里插入图片描述

索引的组成部分:

  • alias:索引别名
  • settings:索引设置,常见设置如分片和副本的数量等。
  • mapping:映射,定义了索引中包含哪些字段,以及字段的类型、长度、分词器等

类型:Type(ES 7.x 之后版本已删除此概念)

从ES 7.x版本开始类型已经被弃用,一个索引只能包含一个类型,在 8.14.2 中,_doc是路径的永久部分,表示端点名称而不是文档类型

索引 API :

  • PUT {index}/_doc/{id}于显式ID
  • POST {index}/_doc 自动生成的 ID

文档:Document

文档是ES中的最小数据单元。
它是一个具有结构化JSON格式的记录。文档可以被索引并进行搜索、更新和删除操作。

文档元数据,所有字段均以下划线开头,为系统字段,用于标注文档的相关信息:

  • _index:文档所属的索引名
  • _type:文档所属的类型名
  • _id:文档唯一id
  • _source: 文档的原始Json数据
  • _version: 文档的版本号,修改删除操作_version都会自增1
  • _seq_no: 和_version一样,一旦数据发生更改,数据也一直是累计的。Shard级别严格递增,保证后写入
    的Doc的_seq_no大于先写入的Doc的_seq_no。
  • _primary_term: _primary_term主要是用来恢复数据时处理当多个文档的_seq_no一样时的冲突,避免Primary
    Shard上的写入被覆盖。每当Primary Shard发生重新分配时,比如重启,Primary选举等,_primary_term会递
    增1。

ElasticSearch索引操作

参考文档:https://www.elastic.co/guide/en/elasticsearch/reference/8.14/index.html

创建索引

格式: PUT /索引名称

索引命名规范:
以小写英文字母命名索引
不要使用驼峰命名法则
如出现多个单词的索引名称,以全小写 + 下划线分隔的方式:如test_index。

ES 索引创建成功之后,以下属性将不可修改
索引名称
主分片数量
字段类型

 #创建索引
 PUT /es_db

默认索引信息如下:

{
  "es_db": {
    "aliases": {},
    "mappings": {},
    "settings": {
      "index": {
        "routing": {
          "allocation": {
            "include": {
              "_tier_preference": "data_content"
            }
          }
        },
         
        "number_of_shards": "1",  #主分片数 
        "provided_name": "es_db",
        "creation_date": "1721033661027",
        
        "number_of_replicas": "1",  #分片副本数
        "uuid": "5plzCOkBRZSoIFUjVCTNjg",
        "version": {
          "created": "8505000"
        }
      }
    }
  }
}

设置 Settings

创建索引的时候可以指定 settings

 PUT <index_name>
 {
 "settings": {}
 }

举例:
比如创建索引时可以设置Settings中分片数和副本数

 #创建索引es_db,指定其主分片数量为 3,每个主分片的副本数量为 2
 PUT /es_db
 {
 "settings" : {
 "number_of_shards" : 3,
 "number_of_replicas" : 2
 }
 }

再比如创建索引时可以指定Settings中IK分词器作为默认分词器

 PUT /es_db
 {
 "settings" : {
 "index" : {
 "analysis.analyzer.default.type": "ik_max_word"
 }
 }
 }

静态索引设置

index.number_of_shards:索引的主分片的个数,默认为 1,此设置只能在创建索引时设置

动态索引设置

可以使用 _setting API 在实时修改的配置项。
index.number_of_replicas:每个主分片的副本数。默认为 1,允许配置为 0。
index.refresh_interval:数据写入磁盘需要时间,这个是设置刷新操作频率的,默认为1s. 可以设置 -1 为禁用刷新。
index.max_result_window:from + size 搜索此索引 的最大值(返回条数),默认为 10000。

使用 _setting 只能修改允许动态修改的配置项

 #修改索引配置,把每个主分片的副本数量修改为 1
 PUT /es_db/_settings
 {
 "index" : {
 "number_of_replicas" : 1
 }
 }

设置 Mapping

ES 中的 mapping 有点类似与关系数据库中表结构的概念,在 MySQL 中,表结构里包含了字段名称,字段的类型还有索引信息等。在 Mapping 里也包含了一些属性,比如字段名称、类型、字段使用的分词器、是否评分、是否创建索引等属性,并且在 ES 中一个字段可以有多个类型。ES中Mapping可以分为动态映射和静态映射

  #查看完整的索引 mapping
 GET /<index_name>/_mappings

  #查看索引中指定字段的 mapping
 GET /<index_name>/_mappings/field/<field_name

mapping 的使用禁忌

ES 没有隐式类型转换
ES 不支持类型修改
生产环境尽可能的避免使用 动态映射(dynamic mapping)

动态映射

在关系数据库中,需要事先创建数据库,然后在该数据库下创建数据表,并创建表字段、类型、长度、主键等,最后才能基于表插入数据。
而Elasticsearch中不需要定义Mapping映射,在文档写入Elasticsearch时,会根据文档字段自动识别类型,这种机制称之为动态映射。

示例

 #创建文档(ES根据数据类型, 会自动创建映射)
 PUT /user/_doc/1
 {
 "name":"mm",
 "age":32,
 "address":"河北"
 }

 #获取文档映射
 GET /user/_mapping

返回信息

{
  "user": {
    "mappings": {
      "properties": {
        "address": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "age": {
          "type": "long"
        },
        "name": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        }
      }
    }
  }
}

静态映射

静态映射也叫做显式映射,即:在索引文档写入之前,人为创建索引并且指定索引中每个字段类型、分词器等参数。

实例

# 创建索引并且指定索引中每个字段类型、分词器、分片与分片备份等参数
PUT /user
{
  "settings": {
    "number_of_shards": "3",
    "number_of_replicas": "2",
    "index" : {
        "analysis.analyzer.default.type": "ik_max_word"
    }
  },
  "mappings": {
    "properties": {
      "name": {
        "type": "keyword"
      },
      "age": {
        "type": "long"
      },
      "address": {
        "type": "text"
      }
    }
  }
}

返回信息

{
  "user": {
    "aliases": {},
    "mappings": {
      "properties": {
        "address": {
          "type": "text"
        },
        "age": {
          "type": "long"
        },
        "name": {
          "type": "keyword"
        }
      }
    },
    "settings": {
      "index": {
        "routing": {
          "allocation": {
            "include": {
              "_tier_preference": "data_content"
            }
          }
        },
        "number_of_shards": "3",
        "provided_name": "user",
        "creation_date": "1721041794614",
        "analysis": {
          "analyzer": {
            "default": {
              "type": "ik_max_word"
            }
          }
        },
        "number_of_replicas": "2",
        "uuid": "fU9JVWEOTweggyi2Hkkmqg",
        "version": {
          "created": "8505000"
        }
      }
    }
  }
}

常用Mapping参数配置

参数名称释义
analyzer指定分析器,只有 text 类型字段支持。
copy_to该参数允许将多个字段的值复制到组字段中,然后可以将其作为单个字段进行查询
dynamic是否可以动态添加新字段,支持以下四个选项:true:(默认)允许动态映射。false:忽略新字段。这些字段不会被索引或搜索,但仍会出现在_source返回的命中字段中。这些字段不会添加到映射中,必须显式添加新字段。runtime:新字段作为运行时字段添加到索引中,这些字段没有索引,是_source在查询时加载的。strict:如果检测到新字段,则会抛出异常并拒绝文档。必须将新字段显式添加到映射中。
doc_values为了提升排序和聚合效率,默认true,如果确定不需要对字段进行排序或聚合,也不需要通过脚本访问字段值,则可以禁用doc值以节省磁盘空间(不支持 text 和 annotated_text)
eager_global_ordinals用于聚合的字段上,优化聚合性能。
enabled这是一个index和doc_value的总开关,如果enabled设置为false,则这个字段将会仅存在于_source中,其对应的index和doc_value都不会被创建。这意味着,该字段将不可以被搜索、排序或者聚合,但可以通过_source获取其原始值。
fielddata与doc_values功能类似,doc_values在磁盘操作,这个在内存操作,查询时内存数据结构,在首次用当前字段聚合、排序或者在脚本中使用时,需要字段为fielddata数据结构,并且创建倒排索引保存到堆中fields 给 field 创建多字段,用于不同目的(全文检索或者聚合分析排序)
format用于格式化代码,如 “data”:{ “type”: “data”, “format”: “yyyy-MM-ddHH:mm:ss”}
index是否对创建对当前字段创建倒排索引,默认true,如果不创建索引,该字段不会通过索引被搜索到,但是仍然会在 source 元数据中展示。
norms是否禁用评分(在filter和聚合字段上应该禁用)
null_value为 null 值设置默认值
search_analyzer设置单独的查询时分析器

示例:

  1. analyzer用法
#创建索引,给address字段指定分析器
PUT /user
{
  "mappings": {
    "properties": {
      "address": {
        "type": "text",
        "analyzer": "ik_max_word"
      }
    }
  }
}
#获取mapping信息
GET /user/_mapping

#返回信息
{
  "user": {
    "mappings": {
      "properties": {
        "address": {
          "type": "text",
          "analyzer": "ik_max_word"
        }
      }
    }
  }
}
  1. copy_to用法

# 创建索引,copy_to可以把两个字段合并到all_text中
PUT /user
{
  "mappings": {
    "properties": {
      "address": {
        "type": "text",
        "copy_to": "all_text", 
        "analyzer": "ik_max_word"
      },
       "name": {
        "type": "keyword",
        "copy_to": "all_text"
      },
      "all_text":{
         "type": "text"
      }
    }
  }
}

# 添加测试数据
put /user/_doc/1
{
  "name": "fox",
  "address": "邯郸"
}

#查询
GET /user/_search
{
  "query": {
    "match": {
      "all_text": "fox邯郸" 
    }
  }
}

#返回信息
{
  "took": 9,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 0.8630463,
    "hits": [
      {
        "_index": "user",
        "_id": "1",
        "_score": 0.8630463,
        "_source": {
          "name": "fox",
          "address": "邯郸"
        }
      }
    ]
  }
}

查询索引

格式: GET /索引名称

 #查询索引
 GET /es_db

 #es_db是否存在
 HEAD /es_db

删除索引

格式: DELETE /索引名称

DELETE /es_db

使用ReIndex重建索引

具体方法:

  1. 如果要推倒现有的映射, 你得重新建立一个静态索引
  2. 然后把之前索引里的数据导入到新的索引里
  3. 删除原创建的索引
  4. 为新索引起个别名, 为原索引名

通过这几个步骤可以实现了索引的平滑过渡,并且是零停机

使用ReIndex重建索引

 # 1. 重新建立一个静态索引
 PUT /user2
 {
 "mappings": {
 "properties": {
 "name": {
 "type": "text"
 },
 "address": {
 "type": "text",
 "analyzer": "ik_max_word"
 }
 }
 }
 }
 
 # 2. 把之前索引里的数据导入到新的索引里
 POST _reindex
 {
 "source": {
 "index": "user"
 },
 "dest": {
 "index": "user2"
 }
 }
 
 # 3. 删除原创建的索引
 DELETE /user
 
 # 4. 为新索引起个别名, 为原索引名
 PUT /user2/_alias/user

 GET /user

ElasticSearch文档操作

示例数据

PUT /es_db
{
  "settings": {
    "index": {
      "analysis.analyzer.default.type": "ik_max_word"
    }
  }
}



PUT /es_db/_doc/1
 {
 "name": "张三",
 "sex": 1,
 "age": 25,
 "address": "广州天河公园",
 "remark": "java developer"
 }
 PUT /es_db/_doc/2
 {
 "name": "李四",
 "sex": 1,
 "age": 28,
 "address": "广州荔湾大厦",
 "remark": "java assistant"
 }

 PUT /es_db/_doc/3
 {
 "name": "王五",
 "sex": 0,
 "age": 26,
 "address": "广州白云山公园",
 "remark": "php developer"
 }

 PUT /es_db/_doc/4
 {
 "name": "赵六",
 "sex": 0,
 "age": 22,
 "address": "长沙橘子洲",
 "remark": "python assistant"
 }

 PUT /es_db/_doc/5
 {
 "name": "张龙",
 "sex": 0,
 "age": 19,
 "address": "长沙麓谷企业广场",
 "remark": "java architect assistant"
 }

 PUT /es_db/_doc/6
 {
 "name": "赵虎",
 "sex": 1,
 "age": 32,
 "address": "长沙麓谷兴工国际产业园",
 "remark": "java architect"
 }

索引文档

  • 格式: [PUT | POST] /索引名称/[_doc | _create ]/id
# 创建文档,指定id
# 如果id不存在,创建新的文档,否则先删除现有文档,再创建新的文档,版本会增加
PUT /es_db/_doc/1
{
  "name": "张三",
  "sex": 1,
  "age": 25,
  "address": "广州天河公园",
  "remark": "java developer"
} 

#创建文档,ES生成id
POST /es_db/_doc
{
  "name": "张三",
  "sex": 1,
  "age": 25,
  "address": "广州天河公园",
  "remark": "java developer"
}

#_create创建文档,指定id,如果id存在会失败
POST /es_db/_create/13
{
  "name": "张三",
  "sex": 1,
  "age": 25,
  "address": "广州天河公园",
  "remark": "java developer"
}

注意:POST和PUT都能起到创建/更新的作用,PUT需要对一个具体的资源进行操作也就是要确定id才能进行更新/创建,而POST是可以针对整个资源集合进行操作的,如果不写id就由ES生成一个唯一id进行创建新文档,如果填了id那就针对这个id的文档进行创建/更新。
create: 如果ID已经存在,会失败

查询文档

  • 根据id查询文档,格式: GET /索引名称/_doc/id

GET /es_db/_doc/1

  • 条件查询 _search,格式: /索引名称/_search

查询前10条文档 , 默认from为0,size为10
GET /es_db/_search

ES Search API提供了两种条件查询搜索方式:

  • REST风格的请求URI,直接将参数带过去
  • 封装到request body中,这种方式可以定义更加易读的JSON格式

URI Query

 #通过URI搜索,使用“q”指定查询字符串,“qery string syntax” KV键值对

 #条件查询, 如要查询age等于28岁的 _searc?q=*:***
 GET /es_db/_search?q=age:28

 #范围查询, 如要查询age在25至26岁之间的_search?q=***[** TO **] 注意: TO必须为大写
 GET /es_db/_search?q=age[25 TO 26]

 #查询年龄小于等于28岁的 :<=
 GET /es_db/_search?q=age:<=28
 #查询年龄大于28前的 :>
 GET /es_db/_doc/_search?q=age:>28

 #分页查询 from=*&size=*
 GET /es_db/_search?q=age[25 TO26]&from=0&size=1

 #对查询结果只输出某些字段 _source=字,字段
 GET /es_db/_search?_source=nam,age

 #对查询结果排序 sort=字段:desc/asc
 GET /es_db/_search?sort=age:desc

DSL Query

  • DSL(Domain Specific Language领域专用语言)查询是使用Elasticsearch的查询语言来构建查询的方式。
 # match 匹配查询,会对查询文本分词后匹配
 GET /es_db/_search
 {
 "query": {
 "match": {
 "address": "广州白云"
 }
 }
 }

 # term 词项查询,属于精确查询,不会对文本分词
 # 思考:能否查到文档?
 GET /es_db/_search
 {
 "query": {
 "term": {
 "address": "广州白云"
 }
 }
 }

修改文档

  • 全量更新,整个json都会替换格式: [PUT | POST] /索引名称/_doc/id

如果文档存在,现有文档会被删除,新的文档会被索引

 # 全量更新,替换整个json
 PUT /es_db/_doc/1/
 {
 "name": "张三",
 "sex": 1,
 "age": 25
 }

 #查询文档
 GET /es_db/_doc/1
  • 使用_update部分更新,格式: POST /索引名称/_update/id

update不会删除原来的文档,而是实现真正的数据更新

 # 部分更新:在原有文档上更新
 # Update -文档必须已经存在,更新只会对相应字段做增量修改
 POST /es_db/_update/1
 {
 "doc": {
 "age": 28
 }
 }

 #查询文档
 GET /es_db/_doc/1
  • 使用 _update_by_query 更新文档

通过查询条件来批量更新文档


POST /es_db/_update_by_query
{
  "query": {
    "match": {
      "address": "广州"
    }
  },
  "script": {
    "source": "ctx._source.age = 666"
  }
}
 #查询文档
GET /es_db/_doc/1

并发场景下修改文档

  • _seq_no和_primary_term是对_version的优化,7.X版本以后的ES默认使用这种方式控制版本,所以当在高并发环境下使用乐观锁机制修改文档时,要带上当前文档的_seq_no和_primary_term进行更新:
POST /es_db/_doc/2?if_seq_no=37&if_primary_term=1
{
  "name": "李四xxx"
}

如果版本号不对,会抛出版本冲突异常,如下:

{
  "error": {
    "root_cause": [
      {
        "type": "version_conflict_engine_exception",
        "reason": "[2]: version conflict, required seqNo [37], primary term [1]. current document has seqNo [38] and primary term [1]",
        "index_uuid": "qDj0iJ3DQXyDRuDQwEtZqg",
        "shard": "0",
        "index": "es_db"
      }
    ],
    "type": "version_conflict_engine_exception",
    "reason": "[2]: version conflict, required seqNo [37], primary term [1]. current document has seqNo [38] and primary term [1]",
    "index_uuid": "qDj0iJ3DQXyDRuDQwEtZqg",
    "shard": "0",
    "index": "es_db"
  },
  "status": 409
}

删除文档

  • 格式: DELETE /索引名称/_doc/id

DELETE /es_db/_doc/1

ElasticSearch文档批量操作

批量操作可以减少网络连接所产生的开销,提升性能

  • 支持在一次API调用中,对不同的索引进行操作
  • 可以在URI中指定Index,也可以在请求的Payload中进行
  • 操作中单条操作失败,并不会影响其他操作
  • 返回结果包括了每一条操作执行的结果

批量写入

批量对文档进行写操作是通过_bulk的API来实现的

  • 请求方式:POST
  • 请求地址:_bulk
  • 请求参数:通过_bulk操作文档,一般至少有两行参数(或偶数行参数)
    • 第一行参数为指定操作的类型及操作的对象(index,type和id)
    • 第二行参数才是操作的数据

参数类似于:

{"actionName":{"_index":"indexName", "_type":"typeName","_id":"id"}}
{"field1":"value1", "field2":"value2"}

actionName:表示操作类型,主要有create,index,delete和update

批量创建文档create

#批量创建, 7.x版本需要指定 "_type":"_doc"才行
POST _bulk
{"create":{"_index":"article","_id":5}}
{"id":3,"title":"河北","content":"河北666","tags":["java", "面向对象"],"create_time":1554015482530}
{"create":{"_index":"article","_id":6}}
{"id":4,"title":"邯郸","content":"邯郸NB","tags":["java", "面向对象"],"create_time":1554015482530}

#查询
GET /article/_mget
{
  "ids":["5","6"]
}

普通创建与全量替换index

 POST _bulk
 {"index":{"_index":"article", "_id":7}}
 {"id":3,"title":"图灵徐庶老师","content":"图灵学院徐庶老师666","tags":["java", "面向对象"],"create_time":1554015482530}
 {"index":{"_index":"article", "_id":8}}
 {"id":4,"title":"图灵诸葛老师","content":"图灵学院诸葛老师NB","tags":["java", "面向对象"],"create_time":1554015482530}

#查询
GET /article/_mget
{
  "ids":["7","8"]
}
  • 如果原文档不存在,则是创建
  • 如果原文档存在,则是替换(全量修改原文档)

批量删除delete

POST _bulk
{"delete":{"_index":"article","_id":7}}
{"delete":{"_index":"article","_id":8}}

批量修改update

POST _bulk
{"update":{"_index":"article","_id":3}}
{"doc":{"title":"6666666666666"}}
{"update":{"_index":"article","_id":4}}
{"doc":{"create_time":1554018421008}}

组合使用

POST _bulk
{"create":{"_index":"article","_id":7}}
{"id":3,"title":"邯郸666","content":"6666666666","tags":["java","面向对象"],"create_time":1554015482530}
{"delete":{"_index":"article","_id":7}}
{"update":{"_index":"article","_id":4}}
{"doc":{"create_time":1554018421008}}

批量读取

es的批量查询可以使用mget和msearch两种。其中mget是需要我们知道它的id,可以指定不同的index,也可以指定返回值source。msearch可以通过字段查询来进行一个批量的查找。

  • _mget
#可以通过ID批量获取不同index和type的数据
GET _mget
{
  "docs": [
    {
      "_index": "es_db",
      "_id": 2
    },
    {
      "_index": "article",
      "_id": 4
    }
  ]
}

#可以通过ID批量获取es_db的数据
GET /es_db/_mget
{
  "docs": [
    {
      "_id": 2
    },
    {
      "_id": 4
    }
  ]
}
 #简化后
GET /es_db/_mget
{
  "ids": [
    "2",
    "4"
  ]
}

  • _msearch
GET /_msearch
{"index":"es_db"}
{"query":{"match_all":{}},"from":0,"size":2}
{"index":"article"}
{"query":{"match_all":{}}}

#index也可以在url中指定
GET /es_db/_msearch
{}
{"query":{"match_all":{}},"from":0,"size":2}
{"index":"article"}
{"query":{"match_all":{}}}

在_msearch中,请求格式和bulk类似。
查询一条数据需要两个对象,第一个设置index。
第二个设置查询语句,语法和search相同。
如果只是查询一个index,我们可以在url中带上index,这样,如果查该index可以直接用空对象表示。

Spring Boot整合ElasticSearch实战

  • 29
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dmlg清风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值