Elasticsearch 快速上手

880 阅读6分钟

Elasticsearch REST API

Elasticsearch提供了全面强大的REST API:

  • 检查集群、节点、索引的健康、状态以及统计信息。
  • 管理你的集群、节点和索引数据、元数据。
  • 对索引进行CRUD。
  • 执行分页、排序、过滤、脚本编写、聚合以及其他高级搜索。

Elasticsearch请求格式: <HTTP Verb> /<Index>/<Type>/<ID>

文档说明

  • 学习的是Elasticsearch v6.7.1。
  • 示例都是用的Kibana,如果不明白Kibana可以看我的或者官网以及其他人的Kibana教程,只需要看DevTools如何使用暂时就够了,也可以用Postman、RestletClient、curl等,能发送REST请求的都可以。

快速入门示例

集群信息

集群健康值:

  • green:一切正常。(集群功能齐全)
  • yellow:所有数据可用,一些副本尚未分配。(集群功能齐全)
  • red:一些数据由于某种原因不可用。(集群部分功能可用)

注意:状态为red时仍然提供搜索服务(在可用的分片中搜索),但你需要尽快的去修复它。

GET /_cat/health?v

epoch      timestamp cluster       status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent
1555378987 01:43:07  elasticsearch green           1         1      4   4    0    0        0             0                  -                100.0%

节点信息

列出所有节点。

GET /_cat/nodes?v

ip        heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
127.0.0.1           49          73  11                          mdi       *      m9Y7FJV

索引信息

列出所有索引。

GET /_cat/indices?v

health status index                           uuid                   pri rep docs.count docs.deleted store.size pri.store.size
green  open   .monitoring-es-6-2019.04.16     IND0TKuCQsyHTH2FDE1zdg   1   0       5478           36      2.7mb          2.7mb
green  open   .kibana_1                       XTsD7vQ7QbukbJpFlkfLQQ   1   0          4            0     14.4kb         14.4kb
green  open   .kibana_task_manager            0G59n4AWQzSxJ6YSHBDPnA   1   0          2            0     12.5kb         12.5kb
green  open   .monitoring-kibana-6-2019.04.16 -SZdui1tTw-srkqmUxzQHw   1   0        684            0    309.2kb        309.2kb

创建索引

创建一个索引:名叫customer,2个分片,0副本。

# PUT /customer
# PUT /customer?pretty
PUT /customer?pretty
{
  "settings": {
    "number_of_shards": 2,
    "number_of_replicas": 0
  }
}

注意:默认是5个分片1个副本,如果只有一个节点,副本分片就会没有地方分配,集群状态就会为YELLOW。

解释一下pretty(pretty-printed),直接看示例
添加pretty时:

{
"acknowledged": true,
"shards_acknowledged": true,
"index": "customer"
}

没有添加pretty时:

{"acknowledged":true,"shards_acknowledged":true,"index":"customer"}

删除索引

删除customer索引。

DELETE /customer?pretty

新增文档

使用PUT新增:id为1,name字段值为“Put Add”。
另外,在新增文档时可以不提前创建好索引与类型,elasticsearch会自动帮你创建。

PUT /customer/_doc/1?pretty
{
  "name": "Put Add"
}

响应

{
  "_index" : "customer",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}

查询刚才新增的数据

GET /customer/_doc/1?pretty

{
  "_index" : "customer",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "_seq_no" : 0,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "name" : "Put Add"
  }
}

使用POST新增:自动生成id

POST /customer/_doc?pretty
{
  "name": "Post Add"
}

响应

{
  "_index" : "customer",
  "_type" : "_doc",
  "_id" : "RYeuJGoB_H2WuLZOyvLU",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}

更新文档

Elasticsearch实际上并不是更新文档,而是创建新文档。

使用PUT更新:ID相同时会替换,也就相当于更新。

PUT /customer/_doc/1?pretty
{
  "name": "PUT Update"
}

响应:_version、result改变了。

{
  "_index" : "customer",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 2,
  "result" : "updated",
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 1,
  "_primary_term" : 1
}

Post更新
1.更新字段

POST /customer/_doc/1/_update?pretty
{
  "doc": {
    "name": "Post Update"
  }
}

2.更新的同时,新增一个字段。

POST /customer/_doc/1/_update?pretty
{
  "doc": {
    "name": "Baozi",
    "age": "21"
  }
}

3.使用脚本更新,将年龄增加5岁

POST /customer/_doc/1/_update?pretty
{
  "script": "ctx._source.age += 5"
}

删除文档

DELETE /customer/_doc/1?pretty
DELETE /customer/_doc/RYeuJGoB_H2WuLZOyvLU?pretty

批量操作

批量操作类型:

  • index:不存在就创建,已存在就更新
  • create:创建
  • delete:删除
  • update:更新

创建两个文档。

POST /customer/_doc/_bulk?pretty
{"index":{"_id":"1"}}
{"name":"Baozi1"}
{"index":{"_id":"2"}}
{"name":"Baozi2"}

更新文档1,删除文档2

POST /customer/_doc/_bulk?pretty
{"update":{"_id":"1"}}
{"doc":{"name":"Baozi1 Updated"}}
{"delete":{"_id":"2"}}

批量操作不会因为其中一个失败中断后续的操作。结束后会按顺序返回响应信息。
示例:增删改报错不会中断,操作类型写错会忽略执行。

POST /customer/_doc/_bulk?pretty
{"index":{"_id":"1"}}
{"name":"Baozi1"}
{"create":{"_id":"1"}}
{"name":"Baozi1"}
{"indexed":{"_id":"2"}}
{"name":"Baozi2"}
{"update":{"_id":"10000"}}
{"doc":{"name":"Baozi10000"}}
{"delete":{"_id":"100000"}}
{"delete":{"_id":"100001"}}

快速入门查询示例

导入数据

使用官方提供的样本数据,格式:

{
    "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"
}
  • 数据复制到文件account.json,之后在文件末尾新起一空行,否则报错bulk request must be terminated by newline

  • 创建索引

PUT /bank?pretty
{
  "settings": {
    "number_of_shards": 2,
    "number_of_replicas": 0
  }
}
  • 导入到ES
    注意@必须要有,否则也会报错bulk request must be terminated by newline
$ curl -H "Content-Type: application/json" -XPOST "localhost:9200/bank/_doc/_bulk?pretty&refresh" --data-binary "@你的文件路径"

URI Search

q:要查询的字段
sort:用来排序的字段,asc升序,desc倒序

GET /bank/_search?q=*&sort=account_number:asc&pretty

返回结果中的字段:
took:ES执行查询的时间,毫秒
timed_out:告诉我们搜索是否超时
_shards:搜索了多少个分片,以及搜索成功/失败的个数。
hits:查询结果
hits.total:符合搜索条件的总数
hits.hits:搜索结果
hits.hits.sort:用来排序的字段,如果没有指定则按分数排序,就不会有这一部分。
hits.max_scorehits.hits._score:相关性分数,分数越高表明与搜索条件越接近。

Request Body Search

示例
match_all:match_all查询,查询所有字段
sort:用来排序的字段。
from:从哪里开始,默认从0开始。
size:查多少个,默认10个。
_source: 指定返回的字段。

GET /bank/_search
{
  "query": {"match_all": {}},
  "sort": [
    {
      "account_number":"asc"
    }
  ],
  "from": 10,
  "size": 2,
  "_source": ["account_number","balance"]
}

match
查询address包含milllane的。
提示:ES存数据时会将mill lane分成milllane做一个分词,想要查询必须包含mill lane可以看下一条match_phrase的示例。

GET /bank/_search
{
  "query": {
    "match": {
      "address": "mill lane"
    }
  }
}

match_phrase
查询address包含mill lane的。

GET /bank/_search
{
  "query": {
    "match_phrase": {
      "address": "mill lane"
    }
  }
}

bool
bool查询的好处在于可以组合多个条件(match、match_phrase等)。
must:满足所有匹配条件。
should:满足其中一个匹配条件。
must_not:必须不满足条件。
filter:过滤内容,并且不进行相关性算分。

must:查询同时包含milllane的address。

GET /bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "address": "mill"
          }
        },
        {
          "match": {
            "address": "lane"
          }
        }
      ]
    }
  }
}

should:查询包含milllane的address。

GET /bank/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "address": "mill"
          }
        },
        {
          "match": {
            "address": "lane"
          }
        }
      ]
    }
  }
}

must_not: 查询不包含

GET /bank/_search
{
  "query": {
    "bool": {
      "must_not": [
        {
          "match": {
            "address": "mill"
          }
        },
        {
          "match": {
            "address": "lane"
          }
        }
      ]
    }
  }
}

组合match、must_not等:查询40岁并且不居住在ID(Idaho的缩写)的人。

GET /bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "age": "40"
          }
        }
      ],
      "must_not": [
        {
          "match": {
            "state": "ID"
          }
        }
      ]
    }
  }
}

filter:对地址包含milllane的,进行过滤,取余额大于30000的。

GET /bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "address": "mill lane"
          }
        }
      ],
      "filter": {
        "range": {
          "balance": {
            "gte": 30000
          }
        }
      }
    }
  }
}

聚合查询
示例一:聚合示例,按state分组,返回前100条聚合结果。
说明:外边一个size设为0,是为了不返回文档只返回聚合结果;field字段下面的size表示terms聚合返回多少条聚合结果,默认10条。

GET /bank/_search
{
  "aggs": {
    "group_by_state": {
      "terms": {
        "field": "state.keyword",
        "size": 100
      }
    }
  }, 
  "size": 0
}

示例二:嵌套聚合,在上一个示例的基础上,计算每个州的平均余额。

GET /bank/_search
{
  "aggs": {
    "group_by_state": {
      "terms": {
        "field": "state.keyword",
        "size": 100
      },
      "aggs": {
        "average_balance": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  },
  "size": 0
}

示例三:聚合排序,接着上一个示例,按照平均余额排序。

GET /bank/_search
{
  "aggs": {
    "group_by_state": {
      "terms": {
        "field": "state.keyword",
        "size": 100,
        "order": {
          "average_balance": "desc"
        }
      },
      "aggs": {
        "average_balance": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  },
  "size": 0
}

示例四:按照年龄分区间,然后再按照性别分组,最后求出每组的平均余额。

GET /bank/_search
{
  "aggs": {
    "group_by_age": {
      "range": {
        "field": "age",
        "ranges": [
          {
            "from": 20,
            "to": 29
          },
          {
            "from": 30,
            "to": 39
          },
          {
            "from": 40,
            "to": 49
          }
        ]
      },
      "aggs": {
        "group_by_gender": {
          "terms": {
            "field": "gender.keyword"
          },
          "aggs": {
            "average_balance": {
              "avg": {
                "field": "balance"
              }
            }
          }
        }
      }
    }
  },
  "size": 0
}