搜索引擎ElasticSearch命令笔记

淡淡的烟草味﹌ 2022-04-04 06:20 391阅读 0赞

搜索引擎ElasticSearch命令笔记

一、安装

(1)下载ES:

curl -L -O https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-版本号.tar.gz

(2)解压:

tar -xzvf elasticsearch-1.1.1.tar.gz -C 保存目录

(3)修改ES的文件权限为777:

chmod 777 elasticsearch-version -R

(4)启动ES

进入ES源码目录,启动ES:

./bin/elasticsearch

如果想在后台以守护进程模式运行,添加-d参数。

我们可以覆盖集群或者节点的名字。我们可以在启动Elasticsearch的时候通过命令行来指定,如下:

./elasticsearch --cluster.name my_cluster_name --node.name my_node_name

(5)打开另一个终端进行测试:

curl 'http://localhost:9200/?pretty'

注意一下有http标记的那一行,它提供了有关HTTP地址(127.0.0.1)和端口(9200)的信息,通过这个地址和端口我们就可以访问我们的节点了。默认情况下,Elasticsearch使用9200来提供对其REST API的访问。如果有必要,这个端口是可以配置的。

查看状态:http://{es-host}:9200| netstat –ano|grep 9300

(6)关闭ES:

当Elasticsearch在前台运行,可以使用Ctrl-C快捷键终止,或者你可以调用shutdown API来关闭:

curl -XPOST 'http://localhost:9200/_shutdown'

二、RESTful API

所有程序语言都可以使用基于HTTP协议,以JSON为数据交互格式的RESTful API,通过9200端口与Elasticsearch进行通信。

1、发送请求

向Elasticsearch发出的请求的组成部分与其它普通的HTTP请求是一样的:

curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'

参数含义:

1)VERB HTTP方法:GET, POST, PUT, HEAD, DELETE
2)PROTOCOL http或者https协议(只有在Elasticsearch前面有https代理的时候可用)
3)HOST Elasticsearch集群中的任何一个节点的主机名,如果是在本地的节点,那么就叫localhost
4)PORT Elasticsearch HTTP服务所在的端口,默认为9200
5)PATH API路径(例如_count将返回集群中文档的数量),PATH可以包含多个组件,例如_cluster/stats或者_nodes/stats/jvm
6)QUERY_STRING 一些可选的查询请求参数,例如?pretty参数将使请求返回更加美观易读的JSON数据
7)BODY 一个JSON格式的请求主体(如果请求需要的话)

2、功能

通过RESTful API,你可以:
1)检查你的集群、节点和索引的健康状态、和各种统计信息
2)管理你的集群、节点、索引数据和元数据
3)对你的索引进行CRUD(创建、读取、更新和删除)和搜索操作
4)执行高级的查询操作,像是分页、排序、过滤、脚本编写(scripting)、小平面刻画(faceting)、聚合(aggregations)和许多其它操作

3、集群健康

使用_cat API检查集群健康:

curl -XGET 'localhost:9200/_cat/health?v&pretty'

当我们询问集群状态的时候,我们要么得到绿色、黄色或红色。绿色代表一切正常(集群功能齐全),黄色意味着所有的数据都是可用的,但是某些复制没有被分配(集群功能齐全),红色则代表因为某些原因,某些数据不可用。注意,即使是集群状态是红色的,集群仍然是部分可用的(它仍然会利用可用的分片来响应搜索请求),但是可能你需要尽快修复它,因为你有丢失的数据。

4、列举节点、索引

  1. curl 'localhost:9200/_cat/nodes?v'
  2. curl 'localhost:9200/_cat/indices?v'
  3. curl -XGET 'localhost:9200/_cat/indices?v&pretty'

5、创建一个索引

curl -XPUT 'localhost:9200/customer?pretty'

默认会有5个分片 1个索引
在Elasticsearch中,文档归属于一种类型(type),而这些类型存在于索引(index)中,我们可以画一些简单的对比图来类比传统关系型数据库:

Relational DB -> Databases -> Tables -> Rows -> Columns

Elasticsearch -> Indices -> Types -> Documents -> Fields

6、删除一个索引

curl -XDELETE 'localhost:9200/customer?pretty'

7、索引并查询一个文档

  1. curl -XPUT 'localhost:9200/customer/external/1?pretty' -d '
  2. {
  3. "name": "John Doe"
  4. }'

为了索引一个文档,我们必须告诉Elasticsearch这个文档要到这个索引的哪个类型(type)下。我们将一个简单的客户文档索引到customer索引、“external”类型中,这个文档的ID是1,这个id是我们在索引的时候指定的。

注意,Elasticsearch在你想将文档索引到某个索引的时候,并不强制要求这个索引被显式地创建。如果customer索引不存在,Elasticsearch将会自动地创建这个索引。

把刚刚索引的文档取出来:

curl -XGET 'localhost:9200/customer/external/1?pretty'

除了一个叫做found的字段来指明我们找到了一个ID为1的文档,和另外一个字段——_source——返回我们前一步中索引的完整JSON文档之外,其它的都没有什么特别之处。

8、修改数据(索引/替换文档)

我们先前看到,怎样索引一个文档。现在我们再次调用那个命令:

  1. curl -XPUT 'localhost:9200/customer/external/1?pretty' -d '
  2. {
  3. "name": "John Doe"
  4. }'

以上的命令将会把这个文档索引到customer索引、external类型中,其ID是1。

如果我们对一个不同(或相同)的文档应用以上的命令,Elasticsearch将会用一个新的文档来替换(重新索引)当前ID为1的那个文档。

  1. curl -XPUT 'localhost:9200/customer/external/1?pretty' -d '
  2. {
  3. "name": "Jane Doe"
  4. }'

以上的命令将ID为1的文档的name字段的值从“John Doe”改成了“Jane Doe”。

如果我们使用一个不同的ID,一个新的文档将会被索引,当前已经在索引中的文档不会受到影响。

  1. curl -XPUT 'localhost:9200/customer/external/2?pretty' -d '
  2. {
  3. "name": "Jane Doe"
  4. }'

以上的命令,将会索引一个ID为2的新文档。

在索引的时候,ID部分是可选的。如果不指定,Elasticsearch将产生一个随机的ID来索引这个文档。Elasticsearch生成的ID会作为索引API调用的一部分被返回。

以下的例子展示了怎样在没有指定ID的情况下来索引一个文档:

  1. curl -XPOST 'localhost:9200/customer/external?pretty' -d '
  2. {
  3. "name": "Jane Doe"
  4. }'

注意,在上面的情形中,由于我们没有指定一个ID,我们使用的是POST而不是PUT。

9、更新文档

注意,Elasticsearch底层并不支持原地更新。在我们想要做一次更新的时候,Elasticsearch先删除旧文档,然后再索引一个更新过的新文档。

将ID为1的文档的name字段改成“Jane Doe”:

  1. curl -XPOST 'localhost:9200/customer/external/1/_update?pretty' -d '
  2. {
  3. "doc": { "name": "Jane Doe" }
  4. }'

将ID为1的文档的name字段改成“Jane Doe”的同时,给它加上age字段:

  1. curl -XPOST 'localhost:9200/customer/external/1/_update?pretty' -d '
  2. {
  3. "doc": { "name": "Jane Doe", "age": 20 }
  4. }'

更新也可以通过使用简单的脚本来进行。使用一个脚本将age加5:

  1. curl -XPOST 'localhost:9200/customer/external/1/_update?pretty' -d '
  2. {
  3. "script" : "ctx._source.age += 5"
  4. }'

在上面的例子中,ctx._source指向当前要被更新的文档。
注意,在写作本文时,更新操作只能一次应用在一个文档上。将来,Elasticsearch将提供同时更新符合指定查询条件的多个文档的功能(类似于SQL的UPDATE-WHERE语句)。

10、删除文档

删除ID为2的文档:

curl -XDELETE 'localhost:9200/customer/external/2?pretty'

我们也能够一次删除符合某个查询条件的多个文档。以下的例子展示了如何删除名字中包含“John”的所有的客户:

  1. curl -XDELETE 'localhost:9200/customer/external/_query?pretty' -d '
  2. {
  3. "query": { "match": { "name": "John" } }
  4. }'

注意,以上的URI变成了/_query,以此来表明这是一个“查询删除”API,其中删除查询标准放在请求体中,但是我们仍然使用DELETE。

11、批处理

除了能够对单个的文档进行索引、更新和删除之外,Elasticsearch也提供了以上操作的批量处理功能,这是通过使用_bulk API实现的。这个功能之所以重要,在于它提供了非常高效的机制来尽可能快的完成多个操作,与此同时使用尽可能少的网络往返。

作为一个快速的例子,以下调用在一次bulk操作中索引了两个文档(ID 1 - John Doe and ID 2 - Jane Doe):

  1. curl -XPOST 'localhost:9200/customer/external/_bulk?pretty' -d '
  2. {"index":{"_id":"1"}}
  3. {"name": "John Doe" }
  4. {"index":{"_id":"2"}}
  5. {"name": "Jane Doe" }
  6. '

以下例子在一个bulk操作中,首先更新第一个文档(ID为1),然后删除第二个文档(ID为2):

  1. curl -XPOST 'localhost:9200/customer/external/_bulk?pretty' -d '
  2. {"update":{"_id":"1"}}
  3. {"doc": { "name": "John Doe becomes Jane Doe" } }
  4. {"delete":{"_id":"2"}}
  5. '

注意上面的delete动作,由于删除动作只需要被删除文档的ID,所以并没有对应的源文档。

bulk API按顺序执行这些动作。如果其中一个动作因为某些原因失败了,将会继续处理它后面的动作。当bulk API返回时,它将提供每个动作的状态(按照同样的顺序),所以你能够看到某个动作成功与否。

三、探索数据

1、样本数据集JSON格式

Elasticsearch是面向文档(document oriented)的,这意味着它可以存储整个对象或文档(document)。然而它不仅仅是存储,还会索引(index)每个文档的内容使之可以被搜索。在Elasticsearch中,你可以对文档(而非成行成列的数据)进行索引、搜索、排序、过滤。这种理解数据的方式与以往完全不同,这也是Elasticsearch能够执行复杂的全文搜索的原因之一。

ELasticsearch使用Javascript对象符号(JavaScript Object Notation),也就是JSON,作为文档序列化格式。

使用JSON文档来表示一个客户的银行账户信息:

  1. {
  2. "account_number": 0,
  3. "balance": 16623,
  4. "firstname": "Bradshaw",
  5. "lastname": "Mckenzie",
  6. "age": 29,
  7. "gender": "F",
  8. "address": "244 Columbus Place",
  9. "employer": "Euron",
  10. "email": "bradshawmckenzie@euron.com",
  11. "city": "Hobucken",
  12. "state": "CO"
  13. }

2、 载入样本数据

  1. curl -XPOST 'localhost:9200/bank/account/_bulk?pretty' --data-binary @accounts.json

3、 搜索API

有两种基本的方式来运行搜索:一种是在REST请求的URI中发送搜索参数,另一种是将搜索参数发送到REST请求体中。请求体方法的表达能力更好,并且你可以使用更加可读的JSON格式来定义搜索。

搜索的REST API可以通过_search端点来访问。下面这个例子返回bank索引中的所有的文档:

  1. curl 'localhost:9200/bank/_search?q=*&pretty'
  2. curl -XGET 'localhost:9200/bank/_search?q=*&sort=account_number:asc&pretty'

我们在bank索引中搜索(_search端点),并且q=*参数指示Elasticsearch去匹配这个索引中所有的文档。

对于这个响应,我们看到了以下的部分:

  1. - took —— Elasticsearch执行这个搜索的耗时,以毫秒为单位
  2. - timed_out —— 指明这个搜索是否超时
  3. - _shards —— 指出多少个分片被搜索了,同时也指出了成功/失败的被搜索的shards的数量
  4. - hits —— 搜索结果
  5. - hits.total —— 能够匹配我们查询标准的文档的总数目
  6. - hits.hits —— 真正的搜索结果数据(默认只显示前10个文档)
  7. - _scoremax_score —— 现在先忽略这些字段

使用请求体方法的等价搜索是:

  1. curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
  2. {
  3. "query": { "match_all": {} }
  4. }'
  5. curl -XGET 'localhost:9200/bank/_search?pretty' -d'
  6. {
  7. "query": { "match_all": {} },
  8. "sort": [
  9. { "account_number": "asc" }
  10. ]
  11. }'

这里的不同之处在于,并不是向URI中传递q=*,取而代之的是,我们在_search API的请求体中POST了一个JSON格式请求体。

注意:一旦你取回了你的搜索结果,Elasticsearch就完成了使命,它不会维护任何服务器端的资源或者在你的结果中打开游标。

4、查询语言(查询DSL)

DSL(Domain Specific Language特定领域语言)以JSON请求体的形式出现。

1)查询匹配所有,但是只查询一个

curl-XPOST'localhost:9200/bank/_search?pretty'-d'{ "query": { "match_all": {} }, "size": 1}'
注意:如果没有指定大小 默认返回10

2)从11位开始查询10个

curl-XPOST'localhost:9200/bank/_search?pretty'-d'{ "query": { "match_all": {} }, "from": 10, "size": 10}'
未指定from的话,默认是 0

3)查询所有,按照 balance 排序

curl-XPOST'localhost:9200/bank/_search?pretty'-d'{ "query": { "match_all": {} }, "sort": { "balance": { "order": "desc" } }}'

4)查询所有数据,但是只获取指定字段

  1. curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
  2. {
  3. "query": { "match_all": {} },
  4. "_source": ["account_number", "balance"],
  5. "size": 1
  6. }'

5)查询 account_method = 20

curl-XPOST'localhost:9200/bank/_search?pretty'-d'{ "query": { "match": { "account_number": 20 } }}'

6)查询地址里包含 mill的

curl-XPOST'localhost:9200/bank/_search?pretty'-d'{ "query": { "match": { "address": "mill" } }}'

7)返回地址中包含“mill”或者包含“lane”的账户:

  1. curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
  2. {
  3. "query": { "match": { "address": "mill lane" } }
  4. }'

8)下面这个例子是match的变体(match_phrase),它会去匹配短语“mill lane”:

  1. curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
  2. {
  3. "query": { "match_phrase": { "address": "mill lane" } }
  4. }'

9)布尔查询

布尔查询允许我们利用布尔逻辑将较小的查询组合成较大的查询。

a) 这个例子组合了两个match查询,这个组合查询返回包含“mill”和“lane”的所有的账户:

  1. curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
  2. {
  3. "query": {
  4. "bool": {
  5. "must": [
  6. { "match": { "address": "mill" } },
  7. { "match": { "address": "lane" } }
  8. ]
  9. }
  10. }
  11. }'

bool must语句指明了,对于一个文档,所有的查询都必须为真,这个文档才能够匹配成功。

b) 查询2个条件 只要有一个满足就返回

下面的例子组合了两个match查询,它返回的是地址中包含“mill”或者“lane”的所有的账户:

  1. curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
  2. {
  3. "query": {
  4. "bool": {
  5. "should": [
  6. { "match": { "address": "mill" } },
  7. { "match": { "address": "lane" } }
  8. ]
  9. }
  10. }
  11. }'

bool should语句指明,对于一个文档,查询列表中,只要有一个查询匹配,那么这个文档就被看成是匹配的。

c) 不包括下面2个搜索项的数据查询

这个例子组合了两个查询,它返回地址中既不包含“mill”,同时也不包含“lane”的所有的账户信息:

  1. curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
  2. {
  3. "query": {
  4. "bool": {
  5. "must_not": [
  6. { "match": { "address": "mill" } },
  7. { "match": { "address": "lane" } }
  8. ]
  9. }
  10. }
  11. }'

bool must_not语句指明,对于一个文档,查询列表中的的所有查询都必须都不为真,这个文档才被认为是匹配的。

d) 多种状态一起查询

我们可以在一个bool查询里一起使用must、should、must_not。此外,我们可以将bool查询放到这样的bool语句中来模拟复杂的、多等级的布尔逻辑。

下面这个例子返回40岁以上并且不生活在ID(daho)的人的账户:

  1. curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
  2. {
  3. "query": {
  4. "bool": {
  5. "must": [
  6. { "match": { "age": "40" } }
  7. ],
  8. "must_not": [
  9. { "match": { "state": "ID" } }
  10. ]
  11. }
  12. }
  13. }'

10) 过滤器

搜索结果中的_score字段表示文档的得分,这个得分是与我们指定的搜索查询匹配程度的一个相对度量。得分越高,文档越相关,得分越低,文档的相关度越低。

Elasticsearch中的所有的查询都会触发相关度得分的计算。对于那些我们不需要相关度得分的场景下,Elasticsearch以过滤器的形式提供了另一种查询功能。过滤器在概念上类似于查询,但是它们有非常快的执行速度,这种快的执行速度主要有以下两个原因:

  • 过滤器不会计算相关度的得分,所以它们在计算上更快一些
  • 过滤器可以被缓存到内存中,这使得在重复的搜索查询上,其要比相应的查询快出许多。

这个例子使用一个被过滤的查询,其返回值是资金在20000到30000之间(闭区间)的账户。

  1. curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
  2. {
  3. "query": {
  4. "filtered": {
  5. "query": { "match_all": {} },
  6. "filter": {
  7. "range": {
  8. "balance": {
  9. "gte": 20000,
  10. "lte": 30000
  11. }
  12. }
  13. }
  14. }
  15. }
  16. }'

通常情况下,要决定是使用过滤器还是使用查询,取决于是否需要相关度得分。如果相关度是不重要的,使用过滤器,否则使用查询。

11) 聚合

聚合提供了分组并统计数据的能力。理解聚合的最简单的方式是将其粗略地等同为SQL的GROUP BY和SQL聚合函数。在Elasticsearch中,你可以在一个响应中同时返回命中的数据和聚合结果。你可以使用简单的API同时运行查询和多个聚合,并以一次返回,这避免了来回的网络通信,这是非常强大和高效的。

a)按照state分组,按照州名的计数倒序排序:

  1. curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
  2. {
  3. "size": 0,
  4. "aggs": {
  5. "group_by_state": {
  6. "terms": {
  7. "field": "state"
  8. }
  9. }
  10. }
  11. }'

注意我们将size设置成0,这样我们就可以只看到聚合结果了,而不会显示命中的结果。

b) 在先前聚合的基础上,现在这个例子计算了每个州的账户的平均余额(还是按照账户数量倒序排序的前10个州):

  1. curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
  2. {
  3. "size": 0,
  4. "aggs": {
  5. "group_by_state": {
  6. "terms": {
  7. "field": "state"
  8. },
  9. "aggs": {
  10. "average_balance": {
  11. "avg": {
  12. "field": "balance"
  13. }
  14. }
  15. }
  16. }
  17. }
  18. }'

注意,我们把average_balance聚合嵌套在了group_by_state聚合之中。这是所有聚合的一个常用模式。你可以任意的聚合之中嵌套聚合,这样你就可以从你的数据中抽取出想要的概述。

c) 基于前面的聚合,现在让我们按照平均余额进行排序:

  1. curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
  2. {
  3. "size": 0,
  4. "aggs": {
  5. "group_by_state": {
  6. "terms": {
  7. "field": "state",
  8. "order": {
  9. "average_balance": "desc"
  10. }
  11. },
  12. "aggs": {
  13. "average_balance": {
  14. "avg": {
  15. "field": "balance"
  16. }
  17. }
  18. }
  19. }
  20. }
  21. }'

d) 下面的例子显示了如何使用年龄段(20-29,30-39,40-49)分组,然后在用性别分组,然后为每一个年龄段的每一个性别计算平均账户余额:

  1. curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
  2. {
  3. "size": 0,
  4. "aggs": {
  5. "group_by_age": {
  6. "range": {
  7. "field": "age",
  8. "ranges": [
  9. {
  10. "from": 20,
  11. "to": 30
  12. },
  13. {
  14. "from": 30,
  15. "to": 40
  16. },
  17. {
  18. "from": 40,
  19. "to": 50
  20. }
  21. ]
  22. },
  23. "aggs": {
  24. "group_by_gender": {
  25. "terms": {
  26. "field": "gender"
  27. },
  28. "aggs": {
  29. "average_balance": {
  30. "avg": {
  31. "field": "balance"
  32. }
  33. }
  34. }
  35. }
  36. }
  37. }
  38. }
  39. }'

12) 高亮

  1. GET /megacorp/employee/_search
  2. {
  3. "query" : {
  4. "match_phrase" : {
  5. "about" : "rock climbing"
  6. }
  7. },
  8. "highlight": {
  9. "fields" : {
  10. "about" : {}
  11. }
  12. }
  13. }

当我们运行这个语句时,会命中与之前相同的结果,但是在返回结果中会有一个新的部分叫做highlight,这里包含了来自about字段中的文本,并且用<em></em>来标识匹配到的单词。

13)分词

http://localhost:9200/_analyze?pretty&analyzer=index_ansj&text=%E5%85%AD%E5%91%B3%E5%9C%B0%E9%BB%84%E4%B8%B8%E8%BD%AF%E8%83%B6%E5%9B%8A

发表评论

表情:
评论列表 (有 0 条评论,391人围观)

还没有评论,来说两句吧...

相关阅读