elasticsearch入门教程
一、简介
Elasticsearch 是位于 Elastic Stack 核心的分布式搜索和分析引擎。Logstash 和 Beats 有助于收集、聚合和丰富您的数据并将其存储在 Elasticsearch 中。Kibana 使您能够以交互方式探索、可视化和分享对数据的见解,并管理和监控堆栈。
Elasticsearch 为所有类型的数据提供近乎实时的搜索和分析。无论您拥有结构化或非结构化文本、数字数据还是地理空间数据,Elasticsearch 都能以支持快速搜索的方式高效地存储和索引它。您可以超越简单的数据检索和聚合信息来发现数据中的趋势和模式。随着您的数据和查询量的增长,Elasticsearch 的分布式特性使您的部署能够随之无缝增长
二、安装
-
docker安装
bash#拉取镜像 本文镜像采用7.12.1版本,7.x之后的版本可以不用安装中文分词搜索,并且7.x之后的版本取消了type 的类型只有一个默认类型_doc docker pull elasticsearch:7.12.1 #运行容器 docker run -itd --name es -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" -e "discovery.type=single-node" --privileged --restart=always -p 9200:9200 -p 9300:9300 elasticsearch:7.12.1
-e "ES_JAVA_OPTS=-Xms512m -Xmx512m" 增加内存限制
-e "discovery.type=single-node" 已单机模式运行
--privileged 已特权模式运行
--restart=always 开机自启动
-p 9200:9200 -p 9300:9300 端口映射
-
压缩包安装
python#下载elasticsearch7.12.1.zip压缩包 wget https://artifacts.elastic.co/downloads/elasticsearch-hadoop/elasticsearch-hadoop-7.12.1.zip #解压缩 unzip elasticsearch-hadoop-7.12.1.zip #切换到elasticsearch目录 cd elasticsearch-hadoop-7.12.1.zip #运行启动文件 ./bin/elasticsearch
如果一切正常现在elasticsearch已经正常启动了,运行在默认的9200端口, 这时你可以打开另一个窗口执行一下命令查看elasticsearch是否正常运行
curl localhost:9200
如果返回以下信息说明服务已经正常启动
json{ "name" : "b7d9cab63b85", "cluster_name" : "docker-cluster", "cluster_uuid" : "IH2XAhDATXqXTZX8kUnpDw", "version" : { "number" : "7.12.1", "build_flavor" : "default", "build_type" : "docker", "build_hash" : "3186837139b9c6b6d23c3200870651f10d3343b7", "build_date" : "2021-04-20T20:56:39.040728659Z", "build_snapshot" : false, "lucene_version" : "8.8.0", "minimum_wire_compatibility_version" : "6.8.0", "minimum_index_compatibility_version" : "6.0.0-beta1" }, "tagline" : "You Know, for Search" }
三、基础概念
-
集群(Cluster)
一个集群就是由一个或多个节点组织在一起,它们共同持有你整个的数据,并一起提供索引和搜索功能。一个集群由一个唯一的名字标识,这个名字默认就是"elasticsearch"。这个名字是重要的,因为一个节点只能通过指定某个集群的名字,来加入这个集群。在产品环境中显式地设定这个名字是一个好习惯,但是使用默认值来进行测试/开发也是不错的。
-
节点(Node)
一个节点是你集群中的一个服务器,作为集群的一部分,它存储你的数据,参与集群的索引和搜索功能。和集群类似,一个节点也是由一个名字来标识的,默认情况下,这个名字是一个随机的漫威漫画角色的名字,这个名字会在启动的时候赋予节点。这个名字对于管理工作来说挺重要的,因为在这个管理过程中,你会去确定网络中的哪些服务器对应于Elasticsearch集群中的哪些节点。
一个节点可以通过配置集群名称的方式来加入一个指定的集群。默认情况下,每个节点都会被安排加入到一个叫做"elasticsearch"的集群中,这意味着,如果你在你的网络中启动了若干个节点,并假定它们能够相互发现彼此,它们将会自动地形成并加入到一个叫做"elasticsearch"的集群中。
在一个集群里,只要你想,可以拥有任意多个节点。而且,如果当前你的网络中没有运行任何Elasticsearch节点,这时启动一个节点,会默认创建并加入一个叫做"elasticsearch"的集群。
-
索引(Index)
一个索引就是一个拥有几分相似特征的文档的集合。比如说,你可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引。一个索引由一个名字来标识(必须全部是小写字母的),并且当我们要对对应于这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。
在一个集群中,如果你想,可以定义任意多的索引。
-
类型(Type)
在一个索引中,你可以定义一种或多种类型。一个类型是你的索引的一个逻辑上的分类/分区,其语义完全由你来定。通常,会为具有一组共同字段的文档定义一个类型。比如说,我们假设你运营一个博客平台并且将你所有的数据存储到一个索引中。在这个索引中,你可以为用户数据定义一个类型,为博客数据定义另一个类型,当然,也可以为评论数据定义另一个类型。
-
文档(Document)
"文档"通常指的是Elasticsearch中的文档(document),而文档在Elasticsearch中是数据的基本单位,类似于关系型数据库中的一行记录。每个文档可以包含多个字段(field),这些字段包含了数据的详情。
在Elasticsearch中,文档是以JSON格式表示的。每个文档都有一个特定的ID,可以在创建文档时指定,也可以由Elasticsearch自动生成。文档可以被索引、搜索、更新和删除。
typescript一个文档是一个可被索引的基础信息单元。比如,你可以拥有某一个客户的文档,某一个产品的一个文档,当然,也可以拥有某个订单的一个文档。文档以JSON(Javascript Object Notation)格式来表示,而JSON是一个到处存在的互联网数据交互格式。 在一个index/type里面,只要你想,你可以存储任意多的文档。注意,尽管一个文档,物理上存在于一个索引之中,文档必须被索引/赋予一个索引的type。
分片和复制(shards & replicas) 一个索引可以存储超出单个结点硬件限制的大量数据。比如,一个具有10亿文档的索引占据1TB的磁盘空间,而任一节点都没有这样大的磁盘空间;或者单个节点处理搜索请求,响应太慢。
markdown为了解决这个问题,Elasticsearch提供了将索引划分成多份的能力,这些份就叫做分片。当你创建一个索引的时候,你可以指定你想要的分片的数量。每个分片本身也是一个功能完善并且独立的"索引",这个"索引"可以被放置到集群中的任何节点上。 分片之所以重要,主要有两方面的原因: - 允许你水平分割/扩展你的内容容量 - 允许你在分片(潜在地,位于多个节点上)之上进行分布式的、并行的操作,进而提高性能/吞吐量 至于一个分片怎样分布,它的文档怎样聚合回搜索请求,是完全由Elasticsearch管理的,对于作为用户的你来说,这些都是透明的。 在一个网络/云的环境里,失败随时都可能发生,在某个分片/节点不知怎么的就处于离线状态,或者由于任何原因消失了,这种情况下,有一个故障转移机制是非常有用并且是强烈推荐的。为此目的,Elasticsearch允许你创建分片的一份或多份拷贝,这些拷贝叫做复制分片,或者直接叫复制。 复制之所以重要,有两个主要原因: - 在分片/节点失败的情况下,提供了高可用性。因为这个原因,注意到复制分片从不与原/主要(original/primary)分片置于同一节点上是非常重要的。 - 扩展你的搜索量/吞吐量,因为搜索可以在所有的复制上并行运行 总之,每个索引可以被分成多个分片。一个索引也可以被复制0次(意思是没有复制)或多次。一旦复制了,每个索引就有了主分片(作为复制源的原来的分片)和复制分片(主分片的拷贝)之别。分片和复制的数量可以在索引创建的时候指定。在索引创建之后,你可以在任何时候动态地改变复制的数量,但是你事后不能改变分片的数量。 默认情况下,Elasticsearch中的每个索引被分片5个主分片和1个复制,这意味着,如果你的集群中至少有两个节点,你的索引将会有5个主分片和另外5个复制分片(1个完全拷贝),这样的话每个索引总共就有10个分片。
四、索引集合
4.1创建索引
新建一个索引(index)以下所有操作均使用bash命令对elasticsearch(以下简称ES)进行操作,以下命令是创建一个名为account的索引。
arduino
curl -X PUT "localhost:9200/account"
创建成功则会返回如下信息
json
{"acknowledged":true,"shards_acknowledged":true,"index":"account"}
4.2创建索引映射(Mapping)非必须
新建索引(index)时如果不手动创建映射(mapping)的话,ES则会自动帮我们创建一个空mapping的索引
,如果我们在创建索引的时候指定字段,ES也会生成我们指定的字段类型,或者默认的类型,以下 是创建一个名为account带mapping的索引(mapping中包含 user、title、desc三个字段)。
vbnet
curl -X PUT "localhost:9200/account" -H "Content-Type: application/json" -d '{
"mappings": {
"properties": {
"user": {
"type": "text"
},
"title": {
"type": "text"
},
"desc": {
"type": "text"
}
}
}
}'
4.3创建索引时添加别名
vbnet
curl -X PUT "localhost:9200/account" -H "Content-Type: application/json" -d '{
"mappings": {
"properties": {
"user": {
"type": "text"
},
"title": {
"type": "text"
},
"desc": {
"type": "text"
}
}
},
"aliases": {
"ac": {
}
}
}'
如果在创建索引(index)的时候没有设置别名(alias)的话,可以使用如下方式将别名(alias)和索引(index)绑定。
arduino
curl -X PUT "localhost:9200/account/_alias/ac"
4.4查看索引定义信息
索引(index)创建之后,可以使用如下方式查看索引定义信息
sql
curl -X GET "localhost:9200/account"
如果执行成功的话,会返回索引(index)的全部信息,如下所示。
json
{
"acount": {
"aliases": {
"ac": {}
},
"mappings": {
"properties": {
"desc": {
"type": "text"
},
"title": {
"type": "text"
},
"user": {
"type": "text"
}
}
},
"settings": {
"index": {
"routing": {
"allocation": {
"include": {
"_tier_preference": "data_content"
}
}
},
"number_of_shards": "1",
"provided_name": "acount",
"creation_date": "1716952600744",
"number_of_replicas": "1",
"uuid": "u83INHdwRRabGleoWGhPFA",
"version": {
"created": "7120199"
}
}
}
}
}
4.5修改索引定义信息
索引(index)的信息包含两部分,静态信息和动态信息,静态信息不可修改动态信息可以修改,如下所示为动态信息修改。
vbnet
curl -X PUT "localhost:9200/account/_settings" -H "Content-Type: application/json" -d '{
"index": {
"number_of_replicas": 2
}
}'
上述示例为修改索引(index)的副本数量为2,当然可以修改索引(index)的其他属性例如 修改映射(mapping)如下所示
vbnet
curl -X PUT "localhost:9200/account/_mapping" -H "Content-Type: application/json" -d '{
"properties": {
"new_field": {
"type": "text"
}
}
}'
如果修改成功则返回如下示例
json
{
"properties": {
"user_id": {
"type": "integer"
}
}
}
4.6判断索引是否存在
判断索引(index)是否存在,使用如下所示,如果存在则返回http status code 200 不存在则返回404。
bash
curl --head "localhost:9200/account"
4.7删除索引
索引(index)删除可以一次删除一个或多个(多个用逗号隔开),也可以一次删除所有(删除所有可以使用_all或者使用通标配*),如下所示。
bash
#删除索引account
curl -X DELETE "localhost:9200/account"
#删除所有索引
curl -X DELETE "localhost:9200/_all"
如果删除成功,则返回如下所示
json
{
"acknowledged": true
}
4.8设置索引的读写
在ES中,可以通过索引设置(index settings)来控制索引的读写权限。具体来说,可以通过设置index.blocks.read_only
和index.blocks.read_only_allow_delete
来控制索引的只读状态。
json
curl -X PUT "localhost:9200/account" -H "Content-Type: application/json" -d '{"index.blocks.read_only": true}'
如果设置成功则返回如下所示
json
{
"acknowledged": true
}
索引的权限有如下几种
index.blocks.read_only:设为true,则索引以及索引的元数据只可读 index.blocks.read_only_allow_delete:设为true,只读时允许删除。 index.blocks.read:设为true,则不可读。 index.blocks.write:设为true,则不可写。 index.blocks.metadata:设为true,则索引元数据不可读写。
4.9设置索引模版
在ES中,可以使用索引模板(index templates)来定义如何创建新索引。通过索引模板,你可以指定默认的设置、映射和别名,以便在创建索引时自动应用这些配置。
以下是一个简单的索引模板示例,它定义了一个索引模板,该模板将自动应用于所有以account-
开头的索引。
vbnet
curl -X PUT "localhost:9200/_template/account_index_template" -H "Content-Type: application/json" -d '{
"index_patterns": ["account-*"],
"settings": {
"number_of_shards": 1,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"@timestamp": {
"type": "date"
},
"message": {
"type": "text"
}
}
}
}'
在这个例子中,索引模板的名称是account_index_template
。index_patterns
定义了匹配的索引模式。settings
定义了分片和副本的数量。mappings
部分定义了字段和它们的类型。
当创建一个新的索引,其名称匹配index_patterns
中定义的模式时,ES会自动应用这个索引模板中的设置。
请注意,索引模板必须在ES集群的每个节点上都是可用的,并且在创建索引后,如果更新了索引模板,那么更改只会应用于后续创建的索引, 执行成功则返回如下结果。
json
{
"acknowledged": true
}
五、数据操作
5.1文档新增
前边我们已经知道怎样创建索引(index),接下来我们就向这个索引中添加一条记录即文档(document)如下示例所示。
vbnet
curl -X POST "localhost:9200/accounts/_doc" -H "Content-Type: application/json" -d '{
"user": "聂风",
"title": "大侠",
"desc": "天下会成员"
}'
添加成功则放回如下结果
json
{
"_index": "accounts",
"_type": "_doc",
"_id": "zG3UuI8BzN5a70AyAmyg",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 4,
"_primary_term": 1
}
5.2文档查询
在ES中文档(document)的查询查询条件有很多种,其中包括wildcard查询、fuzzy查询、regexp查询、match查询,在以下的示例中将挑选几种日常开发中会经常使用的查询方法。
示例一、 使用wildcard查询
在ES中,wildcard
查询允许你使用通配符模式来匹配字符串字段的值。这种查询对于模糊匹配文本非常有用,但需要注意的是,由于通配符可以包含在查询模式中,因此wildcard
查询的性能可能会较差,尤其是在大型文档集或者高选择性的查询中,下面是一个使用wildcard
查询示例将会匹配title子弹以大
字开头的所有记录
vbnet
curl -X GET "localhost:9200/account/_search" -H "Content-Type: application/json" -d '{"query":{
"wildcard":{
"title":"大*"
}
}}'
如果查询成功则返回如下结果
json
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "account",
"_type": "_doc",
"_id": "efwXw48BYSEidx2Al9b0",
"_score": 1.0,
"_source": {
"user": "聂风",
"title": "大侠",
"desc": "天下会成员"
}
}
]
}
}
示例二、 使用fuzzy查询
在ES中,fuzzy查询是一种模糊查询,它允许用户在查询词条中包含一些错误或者不准确的情况下进行匹配。fuzzy查询可以通过在查询字段后面加上波浪号(~)和可选的模糊度参数来实现。模糊度参数是一个0到2之间的数字,默认值为AUTO,它会根据查询词条自动计算模糊度, 以下是一个使用fuzzy查询的示例。
vbnet
curl -X GET "localhost:9200/account/_search" -H "Content-Type: application/json" -d '{ "query": {
"fuzzy": {
"title": {
"value": "大",
"fuzziness": 2
}
}
}}'
如果查询返回结果同示例一返回结果
示例三、 使用regexp查询
在ES中,正则表达式查询(regexp query)允许你根据正则表达式来匹配文本字段的值。这个查询可以用于全文本字段(text
类型)和键值字段(keyword
类型),以下是一个使用 regexp 查询的例子, 以下示例中将会匹配title字段中所有包含侠
字的记录。
vbnet
curl -X GET "localhost:9200/account/_search" -H "Content-Type: application/json" -d '{
"query": {
"regexp": {
"title": ".*侠"
}
}
}'
如果查询成功,返回结果同示例一返回结果
示例四、 使用regexp查询
在ES中,match
查询是一种文本查询,它会对查询字符串进行分析,并在索引中查找与之匹配的文档。它适用于全文搜索场景,并且可以对查询字符串进行智能分析,如分词、过滤停用词等, 以下是一个使用match查询的例子,以下示例中会匹配title字段中值为大侠
的所有记录。
vbnet
curl -X GET "localhost:9200/account/_search" -H "Content-Type: application/json" -d '{
"query": {
"match": {
"title": "大侠"
}
}
}'
如果查询成功,返回结果同示例一返回结果
示例五、 在ES中搜索和匹配多个字段查询
在ES中搜索和匹配多个字段可以通过使用多字段查询实现。多字段查询允许我们在一个查询中同时搜索多个字段,并返回匹配的结果。在ES中,可以使用布尔查询(bool query)结合多个匹配查询(match query)来实现多字段搜索,以下分别是使用布尔查询(bool query)和 结合多个匹配查询(match query)的两个示例。
vbnet
curl -X GET "localhost:9200/account/_search" -H "Content-Type: application/json" -d '{
"query": {
"bool": {
"should": [
{ "match": { "title": "大侠" } },
{ "match": { "user": "聂风" } }
]
}
}
}'
使用多字段匹配查询(multi-match query),这个查询类型可以在一个查询中指定多个字段,并根据字段的权重进行匹配。
vbnet
curl -X GET "localhost:9200/account/_search" -H "Content-Type: application/json" -d '{
"query": {
"multi_match": {
"query": "大侠",
"fields": ["user", "title"]
}
}
}'
如果查询成功,返回结果同示例一返回结果
5.3文档更新
在ES中,更新记录通常使用UPDATE
API。Elasticsearch 7.0+版本引入了一种新的更简单的方法,通过使用_update
端点和if_seq_no
和if_primary_term
乐观并发控制参数来执行无外键更新, 以下是一个文档更新示例。
vbnet
curl -X GET "localhost:9200/account/_update/efwXw48BYSEidx2Al9b0" -H "Content-Type: application/json" -d '{
"doc": {
"user": "步惊云"
}
}'
其中_update/之后的id是创建记录(document)时自己指定的或者指定由ES自动生成的,如果更新成功则会返回如下结果
json
{
"took": 894,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 0.2876821,
"hits": [
{
"_index": "account",
"_type": "_doc",
"_id": "efwXw48BYSEidx2Al9b0",
"_score": 0.2876821,
"_source": {
"user": "步惊云",
"title": "大侠",
"desc": "天下会成员"
}
}
]
}
}
5.4文档删除
在ES中,删除记录通常指的是从索引中删除文档, 其中文档ID
为你想要删除的文档的唯一标识符,以下是删除文档的一个示例。
sql
curl -X DELETE "localhost:9200/account/_doc/efwXw48BYSEidx2Al9b0"
如果删除成功将返回如下结果
json
{
"_index": "account",
"_type": "_doc",
"_id": "efwXw48BYSEidx2Al9b0",
"_version": 3,
"result": "deleted",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 2,
"_primary_term": 1
}