目录
准备好试用Elasticsearch并亲自了解如何使用RESTAPI来存储、搜索和分析数据了吗?
逐步完成以下入门教程:
- 安装、运行Elasticsearch集群。
- 为一些示例文档建立索引
- 使用Elasticsearch查询语言搜索文档。
- 使用分组和指标聚合分析结果。
需要更多背景信息?
查看Elasticsearch简介以学习术语,并了解Elasticsearch的工作原理。 如果您已经熟悉Elasticsearch并想了解它如何与其余组件一起工作,则可能需要跳到Elastic Stack教程,以了解如何使用Elasticsearch,Kibana,Beats和 Logstash。
安装、运行 Elasticsearch
如需用Elasticsearch来测试,您可以在Elasticsearch Service上部署一个托管服务,或在您自己的Linux,macOS或Windows计算机上配置多节点Elasticsearch集群。
在 Elastic Cloud 上运行 Elasticsearch
在Elasticsearch Service上部署托管服务时,该服务与Kibana和APM一起预分配一个三节点Elasticsearch集群。
要在云端部署,你需要:
- 注册免费试用版,然后验证您的电子邮件地址。
- 为您的帐户设置密码。
- 单击创建部署。
创建部署后,就可以为一些文档建立索引了。
本地(Linux、MacOS、Windows)安装运行Elasticsearch
通过从tar或zip安装文件安装,您可以在本地启动Elasticsearch的多个实例,这样可以查看多节点集群的行为。
安装步骤:
- 下载Elasticsearch安装包
curl -L -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.8.0-linux-x86_64.tar.gz
curl -L -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.8.0-darwin-x86_64.tar.gz
- 解压安装包
- Linux:
tar -xvf elasticsearch-7.8.0-linux-x86_64.tar.gz
- MacOs:
tar -xvf elasticsearch-7.8.0-darwin-x86_64.tar.gz
- Windows PowerShell:
Expand-Archive elasticsearch-7.8.0-windows-x86_64.zip
- 从bin目录启动Elasticsearch
- Linux and MacOS:
cd elasticsearch-7.8.0/bin
./elasticsearch
- Windows:
cd elasticsearch-7.8.0\bin
.\elasticsearch.bat
现在,您已经启动运行了一个单节点Elasticsearch集群!
- 启动另外两个Elasticsearch实例,以便您可以看到典型的多节点集群的行为。 您需要为每个节点指定唯一的数据和日志路径。
- Linux and macOS:
./elasticsearch -Epath.data=data2 -Epath.logs=log2
./elasticsearch -Epath.data=data3 -Epath.logs=log3
- Windows:
.\elasticsearch.bat -E path.data=data2 -E path.logs=log2
.\elasticsearch.bat -E path.data=data3 -E path.logs=log3
新增的节点都会被分配唯一的ID。因为您所有节点都在本地运行,所以它们会自动加入第一个节点所在的集群。
- 使用cat health API验证三节点集群是否正在运行。 cat API以比原始JSON更易于阅读的格式返回有关集群和索引的信息。
您可以通过向Elasticsearch rest API提交HTTP请求来直接与集群交互。如果您已经安装并运行了Kibana,您还可以打开 Kibana 通过 Dev Tools 控制台提交请求。
GET /_cat/health?v
该响应表明Elasticsearch集群的状态为绿色,并且具有三个节点:
epoch timestamp cluster status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent
1565052807 00:53:27 elasticsearch green 3 3 6 3 0 0 0 0 - 100.0%
如果您运行是Elasticsearch的单实例,则群集状态将保持为黄色。单节点群集功能齐全,但无法将数据复制到另一个节点以提供备份恢复能力。要使群集状态为绿色,副本分片必须可用。如果群集状态为红色,则某些数据不可用。
使用 cURL 命令与Elasticsearch交互
本指南中的大多数示例都可以转为相应的curl命令,并从 shell 将请求提交给本地 Elasticsearch实例。
例如下面的在 Dev Tools 控制台的请求:
GET /_cat/health?v
在下面shell里面可以用如下请求代替:
curl -X GET "localhost:9200/_cat/health?v"
一个完整的 HTTP 请求参数如下:
curl -X <VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'
变量参数解释如下:
<VERB>
HTTP method,例如,GET、POST、PUT、HEAD或DELETE。
<PROTOCOL>
协议,可用 http 或 https ,如果使用 https 协议跟 Elasticsearch 通信,则需要 Elasticsearch 安全特性来对 http 通信进行加密。
<HOST>
Elasticsearch集群中任何节点的主机名。本地计算机使用localhost。
<PORT>
运行Elasticsearch HTTP服务的端口,默认为9200。
<PATH>
API终端,可以包含多个组件,如_cluster/stats或_node/stats/jvm。
<QUERY_STRING>
任何可选的查询字符串参数。比如 ?pretty 参数将会优雅的打印更易于阅读的JSON返回。
<BODY>
JSON格式的请求正文(如果需要)。
如果启用了Elasticsearch安全功能,您还必须提供有权运行API的有效用户名(和密码)。例如,curl 命令使用 -u 或 --u 参数提供用户信息 。有关运行每个API需要哪些安全权限的详细信息,请参阅 REST APIs。
ElasticSearch使用HTTP状态代码(如200OK)响应每个API请求。除了HEAD请求之外,它还返回JSON格式的响应正文。
其它安装方式
通过从打包文件安装Elasticsearch,您可以轻松地在本地安装和运行多个实例,要运行单个实例,您可以在Docker容器中运行Elasticsearch,在Linux上使用DEB或RPM软件包安装Elasticsearch,在MacOS上使用Homebrew安装,或者在Windows上使用MSI软件包安装程序安装。有关详细信息,请参阅安装Elasticsearch。
创建文档索引
单个文档索引
一旦集群启动并运行,您就可以为数据建立索引了。Elasticsearch有各种各样的访问方式将JSON文档加入Elasticsearch索引。
您可以通过一个简单的PUT请求直接完成此操作,请求需要指定文档的索引、文档的唯一ID以及请求正文中的一个或多个kv键值对:
PUT /customer/_doc/1
{
"name": "John Doe"
}
上面的 customer 就是该文档的索引,上面请求会自动创建 customer 索引,上面 _doc 则是文档的 type。而文档的ID 则是1。
注:因为如下各方面原因,在 Elasticsearch 7版本中,已经将 type 去掉了,但是为了兼容老格式,经常会将 _doc 作为一个唯一的 type。
1、我们经常把二维数据库与ES作类比的方式是不正确的假设。把“index”类比为数据库,“type”类比为表。具体原因是,数据库的表是物理独立的,一个表的列跟另外一张表相同名称的列没有关系,而ES中并非如此,不同type映射类型中具有相同名称的字段在内部由相同的Lucene字段支持。
2、当您想要索引一个deleted字段在不同的type中数据类型不一样。一个类型中为日期字段,另外一个类型中为布尔字段时,这可能会导致ES的存储失败,因为这影响了ES的初衷设计。
3、另外,在一个index中建立很多实体,type,没有相同的字段,会导致数据稀疏,最终结果是干扰了Lucene有效压缩文档的能力,说白了就是影响ES的存储、检索效率。
上面请求会返回下面的JSON结果,包含数据的一些元信息,由于是新创建的一个文档,所以文档版本 _version = 1。
{
"_index" : "customer",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 2,
"failed" : 0
},
"_seq_no" : 26,
"_primary_term" : 4
}
可以立即从集群中的任意节点获得新文档,我们用下面的带文档 ID 的 GET 请求来查看(这里我特意列举了一下在 shell 下的执行命令,):
curl -X GET "localhost:9200/customer/_doc/1?pretty"
你也可以在 Kibana 的 Dev Tools 控制台中获取,跟在 shell 中没有任何差别,
该接口返回了已经被索引了的文档详细信息,包含索引、类型、文档ID、版本等等,如果未找到对应文档, found 则会是 false,返回中的 _source 就是我们创建的原始数据了。
批量文档索引
如果您有很多文档要索引,您可以使用Bulk API批量提交它们。使用批量处理文档操作比单独提交请求要快得多,因为它极大地减少了网络往返的开销。
最佳批处理大小取决于许多因素:文档大小和复杂性、索引和搜索负载大小以及集群可用的资源。一般1,000到5,000个文档会比较好,总的文档大小在5MB到15MB之间。您可以自己试着从这个区间去找最佳的大小。
我们现在来批量插入一下数据以便开始我们的搜索与分析:
- 下载account.json示例数据集。这些随机生成的账户信息数据集包含下面这些字段:
{
"account_number": 0,
"balance": 16623,
"firstname": "Bradshaw",
"lastname": "Mckenzie",
"age": 29,
"gender": "F",
"address": "244 Columbus Place",
"employer": "Euron",
"email": "bradshawmckenzie@euron.com",
"city": "Hobucken",
"state": "CO"
}
- 在shell终端使用下面的 _bulk 请求将帐户数据添加到 bank 索引中:
curl -H "Content-Type: application/json" -XPOST "localhost:9200/bank/_bulk?pretty&refresh" --data-binary "@accounts.json"
curl "localhost:9200/_cat/indices?v"
- 如下返回表明有1000个文档被成功添加到 bank 索引中。
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
yellow open bank l7sSYV2cQXmu6_4rJWVIww 5 1 1000 0 128.6kb 128.6kb
查询入门
一旦你已经批量导入了测试数据,就可以发送请求到 _search 终端来搜索数据了,也可以通过在请求URI中指定索引名称,在请求正文指定 Elasticsearch查询DSL来访问全套搜索功能。
例如,以下请求将搜索 bank 索引中所有文档,返回结果按帐号排序:
GET /bank/_search
{
"query": { "match_all": {} },
"sort": [
{ "account_number": "asc" }
]
}
默认情况下,结果的 hits 部分包括与搜索条件匹配的前10个文档:
{
"took" : 63,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value": 1000,
"relation": "eq"
},
"max_score" : null,
"hits" : [ {
"_index" : "bank",
"_type" : "_doc",
"_id" : "0",
"sort": [0],
"_score" : null,
"_source" : {"account_number":0,"balance":16623,"firstname":"Bradshaw","lastname":"Mckenzie","age":29,"gender":"F","address":"244 Columbus Place","employer":"Euron","email":"bradshawmckenzie@euron.com","city":"Hobucken","state":"CO"}
}, {
"_index" : "bank",
"_type" : "_doc",
"_id" : "1",
"sort": [1],
"_score" : null,
"_source" : {"account_number":1,"balance":39225,"firstname":"Amber","lastname":"Duke","age":32,"gender":"M","address":"880 Holmes Lane","employer":"Pyrami","email":"amberduke@pyrami.com","city":"Brogan","state":"IL"}
}, ...
]
}
}
返回还包含有关搜索请求的以下信息:
- took - Elasticsearch运行查询所需的时间(单位为毫秒)。
- time_out - 请求是否超时。
- _shards - 搜索了多少个分片,以及成功、失败或跳过了多少个分片。
- max_score - 找到的最相关文档的分数(文档与搜索条件相关性)
- hits.total.value - 找到了多少个匹配的文档。
- hits.sort - 文档的排序位置(如果不是按相关性分数排序)。
- hits._score - 文档的相关性分数(使用 match_all 时不适用)。
每个搜索请求都是独立的:ElasticSearch不会在请求中维护任何状态信息。要翻阅搜索结果,可以加上 from 和 page 参数来指定分页的起始位置,每页的大小。
GET /bank/_search
{
"query": { "match_all": {} },
"sort": [
{ "account_number": "asc" }
],
"from": 10,
"size": 10
}
现在您已经了解了如何提交基本的搜索请求,让我们来构建比 match_all 更有趣的查询吧。
要指定字段(如address)匹配特定词条(如mill、lane),可以使用 match 查询。例如,以下请求会搜索 address 字段包含 mill 或 lane 的用户:
GET /bank/_search
{
"query": {
"match": {
"address": "mill lane"
}
}
}
如果要执行短语搜索(更精准的匹配)而不是匹配单个词条,请使用 match_phrase 而不是 match 。例如,以下请求仅匹配address 中包含短语 mill lane 的用户:
GET /bank/_search
{
"query": {
"match_phrase": {
"address": "mill lane"
}
}
}
要构造更复杂的查询,可以使用bool查询来组合多个查询条件。您可以指定条件为必须匹配(must match),可能匹配(should match),排除匹配(must not match)。
例如,以下请求在 bank 索引中搜索 40 岁,但不居住在华盛顿州(DC)的用户:
GET /bank/_search
{
"query": {
"bool": {
"must": [
{ "match": { "age": "40" } }
],
"must_not": [
{ "match": { "state": "DC" } }
]
}
}
}
bool查询中的每个 must , should 和 must_not 元素都称为查询子句。 文档满足must、should字句的程度会影响文档的相关性得分。分数越高,文档就越符合您的搜索条件。默认情况下,Elasticsearch返回结果按相关性分数从高到低排序。
must_not子句中的条件被视为过滤器。它会影响文档是否包含在结果中,但不会影响文档的评分方式。您还可以自己显示的指定任意过滤器,以包括或排除基于结构化数据的文档。
例如,以下请求使用 range 范围过滤器将筛选出 balance 在 20000 到 30000(含)之间的用户。
GET /bank/_search
{
"query": {
"bool": {
"must": { "match_all": {} },
"filter": {
"range": {
"balance": {
"gte": 20000,
"lte": 30000
}
}
}
}
}
}
使用聚合分析结果
Elasticsearch聚合使您能够获得有关搜索结果的元信息,并回答诸如“德克萨斯州有多少账户?”之类的问题。或者“田纳西州的平均账户余额是多少?”您可以在一个请求中搜索文档、筛选,并使用聚合来分析结果。
例如,以下请求使用 terms 聚合来按州对 bank 索引中的所有帐户进行分组,并按降序返回开户数最多的十个州:
GET /bank/_search
{
"size": 0,
"aggs": {
"group_by_state": {
"terms": {
"field": "state.keyword"
}
}
}
}
返回结果中, buckets 是包含了 state (州名)和 doc_count(文档个数)的数组,例如,您可以看到ID(爱达荷州)中有27个账户。由于请求中 size=0,因此返回仅包含聚合结果。
{
"took": 29,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped" : 0,
"failed": 0
},
"hits" : {
"total" : {
"value": 1000,
"relation": "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"group_by_state" : {
"doc_count_error_upper_bound": 20,
"sum_other_doc_count": 770,
"buckets" : [ {
"key" : "ID",
"doc_count" : 27
}, {
"key" : "TX",
"doc_count" : 27
}, {
"key" : "AL",
"doc_count" : 25
}, {
"key" : "MD",
"doc_count" : 25
}, {
"key" : "TN",
"doc_count" : 23
}, {
"key" : "MA",
"doc_count" : 21
}, {
"key" : "NC",
"doc_count" : 21
}, {
"key" : "ND",
"doc_count" : 21
}, {
"key" : "ME",
"doc_count" : 20
}, {
"key" : "MO",
"doc_count" : 20
} ]
}
}
}
您可以组合聚合以构建更复杂的数据汇总请求。 例如,以下请求将求平均聚合嵌套在之前的 group_by_state 聚合内,这样可以计算每个州的平均帐户余额。
GET /bank/_search
{
"size": 0,
"aggs": {
"group_by_state": {
"terms": {
"field": "state.keyword"
},
"aggs": {
"average_balance": {
"avg": {
"field": "balance"
}
}
}
}
}
}
您可以通过指定 terms 聚合中的排序,使用嵌套聚合的结果进行排序,而不是按默认的计数排序:
GET /bank/_search
{
"size": 0,
"aggs": {
"group_by_state": {
"terms": {
"field": "state.keyword",
"order": {
"average_balance": "desc"
}
},
"aggs": {
"average_balance": {
"avg": {
"field": "balance"
}
}
}
}
}
}
除了像这样的基本分组和指标聚合之外,Elasticsearch还提供了专门的聚合,用于对多个字段进行操作,并分析特定类型的数据,如日期、IP地址和地理数据。您还可以通过管道将单个聚合的结果再聚合,以便进行进一步分析。
聚合提供的核心分析功能还支持一些额外高级功能,例如使用机器学习来检测异常。
这是一个起点
现在,您已经建立了一个集群、为一些文档建立了索引并运行了一些查询和聚合,您可能需要:
- 深入研究Elastic Stack教程以安装Kibana,Logstash和Beats,并部署基本的系统监视解决方案。
- 将样本数据集加载到Kibana中,以了解如何将Elasticsearch和Kibana一起用于可视化数据。
- 尝试下列Elastic搜索解决方案中的一种:
- 站点搜索
- 应用程序搜索
- 企业搜索