# Elasticsearch 快速入门

ElasticSearch (opens new window) 是一个开源的搜索引擎,建立在一个全文搜索引擎库 Apache Lucene™ 基础之上。 Lucene 可以说是当下最先进、高性能、全功能的搜索引擎库,​无论是开源还是私有。

但是 Lucene 仅仅只是一个库。为了充分发挥其功能,你需要使用 Java 并将 Lucene 直接集成到应用程序中。 更糟糕的是,您可能需要获得信息检索学位才能了解其工作原理。Lucene 非常 复杂。

ElasticSearch (opens new window) 也是使用 Java 编写的,它的内部使用 Lucene 做索引与搜索,但是它的目的是使全文检索变得简单, 通过隐藏 Lucene 的复杂性,取而代之的提供一套简单一致的 RESTful API。

然而,Elasticsearch 不仅仅是 Lucene,并且也不仅仅只是一个全文搜索引擎。 它可以被下面这样准确的形容:

  • 一个分布式的实时文档存储,每个字段 可以被索引与搜索
  • 一个分布式实时分析搜索引擎
  • 能胜任上百个服务节点的扩展,并支持 PB 级别的结构化或者非结构化数据

官方客户端在Java、.NET、PHP、Python、Ruby、Nodejs和许多其他语言中都是可用的。根据 DB-Engines 的排名显示,ElasticSearch 是最受欢迎的企业搜索引擎,其次是Apache Solr,也是基于Lucene。

# ES 开发指南

中文文档请参考:《Elasticsearch: 权威指南》 (opens new window)

英文文档请参考:《Elasticsearch Reference》 (opens new window)

下载: https://www.elastic.co/cn/downloads/ (opens new window)

# ES API文档

API Conventions (opens new window)

Document APIs (opens new window)

Search APIs (opens new window)

Indices APIs (opens new window)

cat APIs (opens new window)

Cluster APIs (opens new window)

Javascript api (opens new window)

# Logstash

Logstash Reference (opens new window)

Configuring Logstash (opens new window)

Input plugins (opens new window)

Output plugins (opens new window)

Filter plugins (opens new window)

# Kibana DevTools 快捷键

  • Ctrl+i 自动缩进
  • Ctrl+Enter 提交
  • Down 打开自动补全菜单
  • Enter 或 Tab 选中项自动补全
  • Esc 关闭补全菜单

pretty = true在任意的查询字符串中增加pretty参数,会让 Elasticsearch 美化输出(pretty-print)JSON响应以便更加容易阅读。

# Kibana 命令

// 查询集群的磁盘状态
GET _cat/allocation?v

// 获取所有索引
GET _cat/indices

// 按索引数量排序
GET _cat/indices?s=docs.count:desc
GET _cat/indices?v&s=index

// 集群有多少节点
GET _cat/nodes

// 集群的状态
GET _cluster/health?pretty=true
GET _cat/indices/*?v&s=index

//获取指定索引的分片信息
GET logs/_search_shards

...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 集群状态

curl -s -XGET 'http://<host>:9200/_cluster/health?pretty'

//系统正常,返回的结果
{
  "cluster_name" : "es-qwerty",
  "status" : "green",
  "timed_out" : false,
  "number_of_nodes" : 3,
  "number_of_data_nodes" : 3,
  "active_primary_shards" : 1,
  "active_shards" : 2,
  "relocating_shards" : 0,
  "initializing_shards" : 0,
  "unassigned_shards" : 0,
  "delayed_unassigned_shards" : 0,
  "number_of_pending_tasks" : 0,
  "number_of_in_flight_fetch" : 0,
  "task_max_waiting_in_queue_millis" : 0,
  "active_shards_percent_as_number" : 100.0
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 检索文档

POST logs/_search
{
  "query":{
    "range":{
      "createdAt":{
        "gt":"2020-04-25",
        "lt":"2020-04-27",
        "format": "yyyy-MM-dd"
      }
    }
  },
  "size":0,
  "aggs":{
    "url_type_stats":{
      "terms": {
        "field": "urlType.keyword",
        "size": 2
      }
    }
  }
}

POST logs/_search
{
  "query":{
    "range":{
      "createdAt":{
        "gte":"2020-04-26 00:00:00",
        "lte":"now",
        "format": "yyyy-MM-dd hh:mm:ss"
      }
    }
  },
  "size":0,
  "aggs":{
    "url_type_stats":{
      "terms": {
        "field": "urlType.keyword",
        "size": 2
      }
    }
  }
}

POST logs/_search
{
  "query":{
    "range": {
      "createdAt": {
        "gte": "2020-04-26 00:00:00",
        "lte": "now",
         "format": "yyyy-MM-dd hh:mm:ss"
      }
    }
  },
  "size" : 0,
  "aggs":{
    "total_clientIp":{
      "cardinality":{
        "field": "clientIp.keyword"
      }
    },
    "total_userAgent":{
      "cardinality": {
        "field": "userAgent.keyword"
      }
    }
  }
}

POST logs/_search
{
  "size" : 0,
  "aggs":{
    "date_total_ClientIp":{
      "date_histogram":{
        "field": "createdAt",
        "interval": "quarter",
        "format": "yyyy-MM-dd",
        "extended_bounds":{
          "min": "2020-04-26 13:00:00",
          "max": "2020-04-26 14:00:00",
        }
      },
      "aggs":{
        "url_type_api": {
          "terms": {
            "field": "urlType.keyword",
            "size": 10
          }
        }
      }
    }
  }
}

POST logs/_search
{
  "size" : 0,
  "aggs":{
    "total_clientIp":{
      "terms":{
        "size":30,
        "field": "clientIp.keyword"
      }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

# 删除文档

// 删除
POST logs/_delete_by_query {"query":{"match_all": {}}}

// 删除索引
DELETE logs
1
2
3
4
5

# 创建索引

数据迁移本质是索引的重建,重建索引不会尝试设置目标索引,它不会复制源索引的设置。 所以在操作之前设置目标索引,包括设置映射,分片数,副本等。

# 数据迁移

# Reindex from Remoteedit

// Reindex支持从远程Elasticsearch集群重建索引:
POST _reindex
{
  "source": {
    "remote": {
      "host": "http://lotherhost:9200",
      "username": "user",
      "password": "pass"
    },
    "index": "source",
    "query": {
      "match": {
        "test": "data"
      }
    }
  },
  "dest": {
    "index": "dest"
  }
}

// host参数必须包含scheme、host和port(例如https://lotherhost:9200)
// username和password参数可选
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

使用时需要在elasticsearch.yml中配置 reindex.remote.whitelist 属性。可以设置多组(例如,lotherhost:9200, another:9200, 127.0.10.*:9200, localhost:*)。

具体使用可参考 Reindex from Remoteedit (opens new window)

# Elasticsearch-Dump

Elasticsearch-Dump是一个elasticsearch数据导入导出开源工具包。安装、迁移相关执行可以在相同可用区的云主机上进行,使用方便。

需要node环境,npm安装elasticdump

npm install elasticdump -g
elasticdump

// Copy an index from production to staging with analyzer and mapping:
elasticdump \
  --input=http://production.es.com:9200/my_index \
  --output=http://staging.es.com:9200/my_index \
  --type=analyzer
elasticdump \
  --input=http://production.es.com:9200/my_index \
  --output=http://staging.es.com:9200/my_index \
  --type=mapping
elasticdump \
  --input=http://production.es.com:9200/my_index \
  --output=http://staging.es.com:9200/my_index \
  --type=data

// Copy a single shard data:
elasticdump \
  --input=http://es.com:9200/api \
  --output=http://es.com:9200/api2 \
  --params='{"preference" : "_shards:0"}'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

elasticdump 命令其他参数使用参考 Elasticdump Options (opens new window)

# 深度分页

  • elasticsearch 超过10000条数据的分页查询会报异常,官方提供了 search_after 的方式来支持
  • search_after 要求提供上一页两个必须的排序标识
//https://www.elastic.co/guide/en/elasticsearch/reference/5.6/search-request-search-after.html
GET logs/_search
{
  "from":9990,
  "size":10,
  "_source": ["url","clientIp","createdAt"],
  "query":{
    "match_all": {}
  },
  "sort":[
    {
      "createdAt":{
        "order":"desc"
      }
    },
    {
      "_id":{
        "order":"desc"
      }
    }
    ]
}

GET logs/_search
{
  "from":-1,
  "size":10,
  "_source": ["url","clientIp","createdAt"],
  "query":{
    "match_all": {}
  },
  "search_after": [1588042597000, "V363vnEBz1D1HVfYBb0V"],
  "sort":[
    {
      "createdAt":{
        "order":"desc"
      }
    },
    {
      "_id":{
        "order":"desc"
      }
    }
    ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45