搜索引擎ElasticSearch命令笔记

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Fighting_No1/article/details/85014904

搜索引擎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、列举节点、索引

curl 'localhost:9200/_cat/nodes?v'
curl 'localhost:9200/_cat/indices?v'
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、索引并查询一个文档

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

curl -XPOST 'localhost:9200/customer/external?pretty' -d '
 {
   "name": "Jane Doe"
 }'   

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

9、更新文档

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

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

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

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

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

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

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

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

10、删除文档

删除ID为2的文档:

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

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

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

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

11、批处理

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

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

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

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

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

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

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

三、探索数据

1、样本数据集JSON格式

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

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

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

{
	"account_number": 0,
	"balance": 16623,
	"firstname": "Bradshaw",
	"lastname": "Mckenzie",
	"age": 29,
	"gender": "F",
	"address": "244 Columbus Place",
	"employer": "Euron",
	"email": "[email protected]",
	"city": "Hobucken",
	"state": "CO"
}

2、 载入样本数据

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

3、 搜索API

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

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

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

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

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

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

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

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
 {
   "query": { "match_all": {} }
 }'
 
curl -XGET 'localhost:9200/bank/_search?pretty' -d'
{
  "query": { "match_all": {} },
  "sort": [
    { "account_number": "asc" }
  ]
}'

这里的不同之处在于,并不是向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)查询所有数据,但是只获取指定字段

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

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”的账户:

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

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

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

9)布尔查询

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

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

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": {
    "bool": {
      "must": [
        { "match": { "address": "mill" } },
        { "match": { "address": "lane" } }
      ]
    }
  }
}'

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

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

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

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": {
    "bool": {
      "should": [
        { "match": { "address": "mill" } },
        { "match": { "address": "lane" } }
      ]
    }
  }
}'

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

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

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

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": {
    "bool": {
      "must_not": [
        { "match": { "address": "mill" } },
        { "match": { "address": "lane" } }
      ]
    }
  }
}'

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

d) 多种状态一起查询

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

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

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": {
    "bool": {
      "must": [
        { "match": { "age": "40" } }
      ],
      "must_not": [
        { "match": { "state": "ID" } }
      ]
    }
  }
}'

10) 过滤器

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

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

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

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

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
      {
        "query": {
          "filtered": {
            "query": { "match_all": {} },
            "filter": {
              "range": {
                "balance": {
                  "gte": 20000,
                  "lte": 30000
                }
              }
            }
          }
        }
      }'

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

11) 聚合

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

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

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
       {
         "size": 0,
         "aggs": {
           "group_by_state": {
             "terms": {
               "field": "state"
             }
           }
         }
       }'

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

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

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "size": 0,
  "aggs": {
    "group_by_state": {
      "terms": {
        "field": "state"
      },
      "aggs": {
        "average_balance": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  }
}'

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

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

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
 {
   "size": 0,
   "aggs": {
     "group_by_state": {
       "terms": {
         "field": "state",
         "order": {
           "average_balance": "desc"
         }
       },
       "aggs": {
         "average_balance": {
           "avg": {
             "field": "balance"
           }
         }
       }
     }
   }
 }'

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

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "size": 0,
  "aggs": {
    "group_by_age": {
      "range": {
        "field": "age",
        "ranges": [
          {
            "from": 20,
            "to": 30
          },
          {
            "from": 30,
            "to": 40
          },
          {
            "from": 40,
            "to": 50
          }
        ]
      },
      "aggs": {
        "group_by_gender": {
          "terms": {
            "field": "gender"
          },
          "aggs": {
            "average_balance": {
              "avg": {
                "field": "balance"
              }
            }
          }
        }
      }
    }
  }
}'

12) 高亮

GET /megacorp/employee/_search
{
    "query" : {
        "match_phrase" : {
            "about" : "rock climbing"
        }
    },
    "highlight": {
        "fields" : {
            "about" : {}
        }
    }
}

当我们运行这个语句时,会命中与之前相同的结果,但是在返回结果中会有一个新的部分叫做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

猜你喜欢

转载自blog.csdn.net/Fighting_No1/article/details/85014904