Kibana在ES中,增加了三个索引,.apm-agent-configuration、.kibana_1、.kibana_task_manager_1
一个Elasticsearch集群可以包含多个索引,相应的每个索引可以包含多个类型。这些不同的类型存储着多个文档,每个文档又有多个属性 。
索引(名词):如前所述,一个 索引 类似于传统关系数据库中的一个 数据库 ,
是一个存储关系型文档的地方。 索引 (index) 的复数词为 indices 或 indexes 。
索引(动词):索引一个文档 就是存储一个文档到一个 索引 (名词)中以便被检索和查询。这非常类似于 SQL 语句中的
INSERT 关键词,除了文档已存在时,新文档会替换旧文档情况之外。
倒排索引:关系型数据库通过增加一个 索引 比如一个 B树(B-tree)索引 到指定的列上,以便提升数据检索速度。
Elasticsearch 和 Lucene 使用了一个叫做 倒排索引 的结构来达到相同的目的。
默认的,一个文档中的每一个属性都是 被索引 的(有一个倒排索引)和可搜索的。一个没有倒排索引的属性是不能被搜索到的。
一个文档不只有数据。它还包含了元数据(metadata)——关于文档的信息。
_index:文档存储的地方,必须是全部小写,不能以下划线开头,不能包含逗号。
_type:文档代表的对象的类,可以是大写或小写,不能包含下划线或逗号。
_id:文档的唯一标识,可以自定义 _id ,也可以让Elasticsearch帮你自动生成
在7.x以后去掉了type的概念。Elasticsearch 为何要在7.X版本中去除type的概念?
Elasticsearch是一个基于Apache Lucene(TM)的开源搜索引擎。无论在开源还是专有领域,Lucene可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库。
Elasticsearch 是一种NoSQL数据库(非关系型数据库),和常规的关系型数据库(比如:MySQL,Oralce等)的基本概念,对应关系如下:
Elasticsearch:index --> type --> documents --> field
MySQL: 数据库 --> 数据表 --> 行 --> 列
mappings相当于数据库中的表结构
相比数据库优势:
1.自动分片
2.倒排索引搜索,毫秒级返回搜索结果
3.基于文档搜索,而非基于字段搜索
为何要去除 type 的概念?
答: 因为 Elasticsearch 设计初期,是直接查考了关系型数据库的设计模式,存在了 type(数据表)的概念。
但是,其搜索引擎是基于 Lucene 的,这种 “基因”决定了 type 是多余的。 Lucene 的全文检索功能之所以快,是因为 倒序索引 的存在。
而这种 倒序索引 的生成是基于 index 的,而并非 type。多个type 反而会减慢搜索的速度。
为了保持 Elasticsearch “一切为了搜索” 的宗旨,适当的做些改变(去除 type)也是无可厚非的,也是值得的。
curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'
#查看集群健康信息
caoming@caoming-HP:~/soft$ curl -XGET "10.143.86.113:9200/_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
1610940837 03:33:57 ES_7.6.2_Cluster green 3 3 16 8 0 0 0 0 - 100.0%
#查看集群中的节点信息
caoming@caoming-HP:~/soft$ curl -XGET "10.143.86.113:9200/_cat/nodes?v"
ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
10.143.86.113 23 57 0 0.13 0.04 0.04 dilm - node-cts
10.143.86.118 26 89 0 0.06 0.02 0.01 dilm - node-mutian
10.143.86.117 13 90 0 0.98 0.29 0.09 dilm * node-caoming
#查看集群中的索引信息。
caoming@caoming-HP:~/soft$ curl -XGET "10.143.86.113:9200/_cat/indices?v"
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
green open filebeat-7.6.2-2021.01.13-000001 wR2lOdYHRluSaBqwutaLww 2 1 4 0 70kb 34.9kb
green open .kibana_task_manager_1 ISrxBupfRQyMCjWJhZWOvA 1 1 2 1 43.9kb 26.8kb
green open .apm-agent-configuration HO8gLx1QQ1uM1E0HnmjLQw 1 1 0 0 566b 283b
green open ilm-history-1-000001 P4dAz4x-Q2OyvjmF0TZqrg 1 1 18 0 64.9kb 32.4kb
green open .kibana_1 F1cK46gzS_-tuzxdzdVPeA 1 1 12 5 80.1kb 40.1kb
green open system_log-2021.01.14 8qdBHoQtSHiyS9WRdEBfMA 1 1 1 0 25.2kb 12.6kb
green open system_log-2021.01.15 odCTpuM0RXmOBqYh0mG3sg 1 1 2 0 49kb 24.4kb
#查看集群中文档的数量 -i包含头信息
caoming@caoming-HP:~/soft$ curl -i -XGET 'http://10.143.86.113:9200/_count?pretty'
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-length: 114
{
"count" : 1,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
}
}
大多数情况下,我们想在索引创建的时候就将我们所需的mapping和其他配置确定好。下面的操作就可以在创建索引的同时,创建settings和mapping。
curl -H 'Content-Type:application/json' -XPUT "10.143.86.113:9200/index_test" -d '
{
"settings": {
"index": {
"number_of_replicas": "1", #设置复制数
"number_of_shards": "1" #设置主分片数
}
},
"mappings": { #创建mapping
"properties": {
"name": {
"type": "text"
},
"age": {
"type": "integer"
}
}
}
}'
使用Kibana
#创建一个新的索引。
PUT employee
{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "employee"
}
服务器返回一个 JSON 对象,里面的acknowledged字段表示操作成功。
#删除索引
DELETE employee
{
"acknowledged" : true
}
PUT /employee/_create/1
{
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
返回结果
{
"_index" : "employee",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}
_version: Elasticsearch中每个文档都有版本号,每当文档变化(包括删除)都会使 _version
查询employee索引下ID为1的成员
GET employee/_doc/1
{
"_index" : "employee",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests" : [
"sports",
"music"
]
}
}
#查询索引为employee的所有成员
GET employee/_search
{
"took" : 2, #花费时间2ms
"timed_out" : false, #请求是否超时
"_shards" : { #搜索了多少分片,成功、失败或者跳过了多个分片
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2, #找到的文档总数
"relation" : "eq"
},
"max_score" : 1.0, #最相关的文档分数
"hits" : [
{
"_index" : "employee",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0, #文档的相关性算分 (match_all 没有算分)
"_source" : {
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests" : [
"sports",
"music"
]
}
},
{
"_index" : "employee",
"_type" : "_doc",
"_id" : "5",
"_score" : 1.0,
"_source" : {
"name" : "John Doe",
"sex" : "male"
}
}
]
}
}
每个搜索请求都是独立的:Elasticsearch 不维护任何请求中的状态信息。
如果做分页的话,请在请求中指定 From 和 Size 参数。
GET employee/_search
{
"query": { "match_all": {} },
"sort": [
{ "age": "asc" }
],
"from": 0,
"size": 2
}
增加新的雇员
PUT /employee/_doc/2
{
"first_name" : "Jane",
"last_name" : "Smith",
"age" : 32,
"about" : "I like to collect rock albums",
"interests": [ "music" ]
}
更新
PUT /employee/_doc/3
{
"first_name" : "Jane",
"last_name" : "Smith",
"age" : 32,
"about" : "I like to collect rock albums.", #增加了一个字符.
"interests": [ "music" ]
}
增加另外一个新的雇员
PUT /employee/_doc/5
{
"name": "John Doe",
"sex" : "male"
}
#查看数据库结构
GET employee
{
"employee" : {
"aliases" : { },
"mappings" : {
"properties" : {
"about" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"age" : {
"type" : "long"
},
"first_name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"interests" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"last_name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
},
"settings" : {
"index" : {
"creation_date" : "1611040131498",
"number_of_shards" : "1",
"number_of_replicas" : "1",
"uuid" : "prHBZz2gTRaYDzwJYdEfMw",
"version" : {
"created" : "7060299"
},
"provided_name" : "employee"
}
}
}
}
match是匹配其中一个字符串就满足条件
GET employee/_search
{
"query": { "match": { "about": "rock climbing" } } #匹配rock或者climbing
}
match_phrase是全字符串匹配
GET employee/_search
{
"query": { "match_phrase": { "about": "rock climbing" } } #匹配"rock climbing"
}
如果要构造更复杂的查询,可以使用布尔查询来组合多个查询条件,must match、should match、must not match
GET /employee/_search
{
"query": {
"bool": {
"must": [
{ "match": { "age": "25" } }
],
"must_not": [
{ "match": { "first_name": "ab" } }
]
}
}
}
GET /employee/_search
{
"query": {
"bool": {
"filter": {
"range":{
"age": {
"gte": 0,
"lte": 40
}
}
},
"must_not": [
{ "match": { "first_name": "ab" } }
]
}
}
}
通常, GET 请求将返回文档的全部,存储在 _source 参数中.请求个别字段可以使用 _source 参数。多个字段可以使用逗号分隔:
GET /employee/_doc/1?_source=first_name,age
{
"_index" : "employee",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
"first_name" : "John",
"age" : 25
}
}
只想得到 _source 字段而不要其他的元数据:
GET /employee/_doc/1/_source
{
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests" : [
"sports",
"music"
]
}
GET /employee/_search?q=age:32
Query-string搜索通过命令非常方便地进行临时性的即席搜索 ,但它有自身的局限性(参见 轻量 搜索 )。
Elasticsearch 提供一个丰富灵活的查询语言叫做 查询表达式 , 它支持构建更加复杂和健壮的查询。
领域特定语言(DSL), 使用JSON构造了一个请求。我们可以像这样重写之前的查询所有名为 Smith 的搜索 :
GET /employee/_search
{
"query" : {
"match" : {
"first_name" : "John"
}
}
}
聚合分析
Elasticsearch 有一个功能叫聚合(aggregations),允许我们基于数据生成一些精细的分析结果。
你可以搜索文档,过滤 hits,使用聚合去分析并返回结果。
GET /employee/_search
{
"aggs": {
"group_by_state": {
"terms": {
"field": "age"
}
}
}
}
{
"took" : 3,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "employee",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests" : [
"sports",
"music"
]
}
},
{
"_index" : "employee",
"_type" : "_doc",
"_id" : "2",
"_score" : 1.0,
"_source" : {
"first_name" : "ab",
"last_name" : "mark",
"age" : 32,
"about" : "I love rock a climbing",
"interests" : [
"sports",
"music"
]
}
},
{
"_index" : "employee",
"_type" : "_doc",
"_id" : "3",
"_score" : 1.0,
"_source" : {
"first_name" : "ab",
"last_name" : "mark",
"age" : 32,
"about" : "I love a climbing",
"interests" : [
"sports",
"music"
]
}
}
]
},
"aggregations" : {
"group_by_state" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : 32,
"doc_count" : 2
},
{
"key" : 25,
"doc_count" : 1
}
]
}
}
}
GET /employee/_search
{
"aggs": {
"group_by_state": {
"avg": {
"field": "age"
}
}
}
}
{
......
"aggregations" : {
"group_by_state" : {
"value" : 29.666666666666668
}
}
}