須要明白的問題
什麼是倒排索引?它的組成是什麼?node
常見的相關性算分方法有哪些?linux
爲何查詢語句沒有返回預期的文檔?git
經常使用的數據類型有哪些?Text和Keyword的區別是什麼?es6
集羣是如何搭建起來的?是如何實現故障轉移的?github
Shard具體是由什麼組成的?json
Elastic Stack
構建在開源基礎之上, Elastic Stack 讓您可以安全可靠地獲取任何來源、任何格式的數據,而且可以實時地對數據進行搜索、分析和可視化瀏覽器
Elasticsearch 是基於 JSON 的分佈式搜索和分析引擎,專爲實現水平擴展、高可用和管理便捷性而設計。安全
Kibana 可以以圖表的形式呈現數據,而且具備可擴展的用戶界面,供您全方位配置和管理 Elastic Stack。微信
Logstash 是動態數據收集管道,擁有可擴展的插件生態系統,可以與 Elasticsearch 產生強大的協同做用。數據結構
Beats 是輕量型採集器的平臺,從邊緣機器向 Logstash 和 Elasticsearch 發送數據。
基礎概念
文檔 Document :用戶存儲在ES中的數據文檔
索引 Index :由具備一些相同字段的文檔的集合
類型 Type : 容許將不一樣類型的文檔存儲在同一索引中,6.0開始官方不容許在一個index下創建多個type,統一type名稱:doc
節點 Node :一個Elasticsearch的運行實例,是集羣的構成單元,存儲部分或所有數據,並參與集羣的索引和搜索功能
集羣 Cluster :由一個或多個節點組成的集合,共同保存全部的數據,對外提供服務(包括跨全部節點的聯合索引和搜索功能等)
分片 Shards :分片是爲了解決存儲大規模數據的問題,將數據切分分別存儲到不一樣的分片中
副本 Replicas :副本能夠在分片或節點發生故障時提升可用性,並且因爲能夠在全部副本上進行並行搜索,因此也能夠提升集羣的吞吐量
近實時 Near Realtime(NRT):從索引文檔到可搜索文檔的時間有一點延遲(一般爲一秒)
note:
在建立索引的時候若是沒有配置索引Mapping,一個索引默認有5個shard和1個副本,一個索引總共有10個shard(算上副本shard)
Elasticsearch 的shard其實是一個Lucene索引,截止Lucene-5843,一個Lucene索引限制的最大文檔數爲2,147,483,519 (= Integer.MAX_VALUE - 128)
安裝Elasticsearch & Kibana
ES和Kibana的安裝很簡單,前提須要先安裝好Java8,而後執行如下命令便可
elasticsearch單節點最簡安裝
# 在Ubuntu16.04上安裝,方式有不少種,選擇二進制壓縮包的方式安裝
# 1. 在普通用戶家目錄下,下載壓縮包
curl -L -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.3.2.tar.gz
# 2. 解壓
tar -xvf elasticsearch-6.3.2.tar.gz
# 3. 移動至/opt目錄下
sudo mv elasticsearch-6.3.2 /opt
# 4. 修改配置文件elasticsearch.yml中的 network.host 值爲 0.0.0.0,其餘的配置參考官方文檔
cd /opt/elasticsearch-6.3.2vi config/elasticsearch.yml
# 5. 啓動單節點,而後瀏覽器訪問host:9200便可看到ES集羣信息
bin/elasticsearch
kibana最簡安裝
wget https://artifacts.elastic.co/downloads/kibana/kibana-6.3.2-linux-x86_64.tar.gz
shasum -a 512 kibana-6.3.2-linux-x86_64.tar.gz
tar -xzf kibana-6.3.2-linux-x86_64.tar.gz
sudo mv kibana-6.3.2-linux-x86_64 /optcd /opt/kibana-6.3.2-linux-x86_64
# 修改 config/kibana.yml中 server.host: 0.0.0.0# 啓動Kibana,訪問 host:5601便可進入kibana界面
交互方式 Rest API
Elasticsearch集羣對外提供RESTful API
Curl命令行
Kibana Devtools
Java API
其餘各類API,如Python API等
note: 咱們後面主要使用 Kibana Devtools 這種交互方式
數據類型
字符串: text(分詞), keyword(不分詞)
數值型: long, integer, byte, double, float, half_float, scaled_float
布爾: boolean
日期: date
二進制: binary
範圍類型: integer_range, float_range, long_range, double_range, date_range
複雜數據類型: Array, Object, Nested
地理: geo_point, geo_shape
專業: ip,completion, token_count, murmur3, Percolator, join
組合的
探索ES集羣
使用_cat API探索集羣的健康狀況
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_percent1534319381 15:49:41 elasticsearch green 3 3 118 59 0 0 0 0 - 100.0%
集羣的健康狀態(status)有三種:
green:一切正常(集羣功能齊全)
yellow:全部數據均可用,但存在一些副本未分配(羣集功能齊全)
red:一些數據因爲某種緣由不可用(羣集部分功能失效)
查看節點信息
GET /_cat/nodes?v
# 結果(個人ES集羣安裝了三個節點)ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name10.100.97.207 30 96 13 0.15 0.08 0.08 mdi * master10.100.97.246 68 96 3 0.00 0.00 0.00 mdi - hadoop210.100.98.22 15 97 2 0.00 0.02 0.04 mdi - hadoop3
查看索引信息
GET /_cat/indices?v
# 結果health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
green open logstash-2015.05.20 4BjPjpq6RhOSCNUPMsY0MQ 5 1 4750 0 46.8mb 24.5mb
green open logstash-2015.05.18 mDkUKHSWR0a8UeZlKzts8Q 5 1 4631 0 45.6mb 23.8mb
green open hockey g1omiazvRSOE117w_uy_wA 5 1 11 0 45.3kb 22.6kb
green open .kibana AGdo8im_TxC04ARexUxqxw 1 1 143 10 665.6kb 332.8kb
green open shakespeare 5009bDa7T16f5qTeyOdTlw 5 1 111396 0 43.9mb 22mb
green open logstash-2015.05.19 az4Jen4nT7-J9yRYpZ0A9A 5 1 4624 0 44.7mb 23.1mb
...
操做數據
插入文檔並查詢
# 插入一個文檔PUT /customer/_doc/1?pretty
{ "name": "John Doe"}# 結果{ "_index": "customer", "_type": "_doc", "_id": "1", "_version": 1, "result": "updated", "_shards": { "total": 2, "successful": 2, "failed": 0
}, "_seq_no": 1, "_primary_term": 1}# 查詢該文檔GET /customer/_doc/1#結果{ "_index": "customer", "_type": "_doc", "_id": "1", "_version": 1, "found": true, "_source": { "name": "John Doe"
}
}
note:
customer
爲索引名,_doc
爲type,1爲文檔_id,須要注意的是:在es6.x建議索引的type值固定爲_doc
,在以後的版本將刪除type了;文檔id若不指定,es會自動分配一個_id給文檔插入文檔後,查看索引信息
GET /_cat/indices?v
能夠看到多了 customer 的索引信息文檔結果,_source字段是原始的json內容,其餘的爲文檔元數據
文檔元數據
用於標註文檔的元信息
_index: 文檔所在的索引名
_type: 文檔所在的類型名
_id: 文檔的惟一id
_uid: 組合id,由_type和_id組成(6.0開始_type再也不起做用,同_id同樣)
_source: 文檔的原始json數據,能夠從這裏獲取每一個字段的內容
_all: 整合全部字段內容到該字段,默認禁用
_routing 默認值爲 _id,決定文檔存儲在哪一個shard上:
shard_num = hash(_routing) % num_primary_shards
刪除索引
DELETE customer#結果{ "acknowledged": true}GET /_cat/indices?v# 再次查看索引信息,能夠發現 customer 不存在,已被刪除
更新文檔
PUT /customer/_doc/1?pretty{ "name": "John Doe"}
POST /customer/_doc/1/_update{ "doc": { "name": "Jane Doe" }
}
POST /customer/_doc/1/_update{ "doc": { "name": "Jane Doe", "age": 20 }
}# 能夠看到 \_version的值一直在增長
刪除文檔
DELETE /customer/_doc/2
批量操做
es提供了_bulk API供批量操做,能夠提升索引、更新、刪除等操做的效率
_bulk操做的類型有四種:
index 索引:若已存在,則覆蓋,文檔不存在則建立
create 建立:文檔不存在則異常
delete 刪除
update 更新
# _bulk 任務:# 1. index建立 customer索引下id爲3的文檔# 2. delete刪除 customer索引下id爲3的文檔# 3. create建立 customer索引下id爲3的文檔# 4. update更新 customer索引下id爲3的文檔POST _bulk
{"index":{"_index":"customer","_type":"_doc","_id":"3"}}
{"name":"whirly"}
{"delete":{"_index":"customer","_type":"_doc","_id":"3"}}
{"create":{"_index":"customer","_type":"_doc","_id":"3"}}
{"name":"whirly2"}
{"update":{"_index":"customer","_type":"_doc","_id":"3"}}
{"doc":{"name":"whirly3"}}
note:
批量查詢用的是 Multi Get API
探索數據
一個簡單的數據集,數據結構以下:
{ "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"}
導入這個簡單的數據集到es中
# 下載wget https://raw.githubusercontent.com/elastic/elasticsearch/master/docs/src/test/resources/accounts.json# 導入curl -H "Content-Type: application/json" -XPOST "localhost:9200/bank/_doc/_bulk?pretty&refresh" --data-binary "@accounts.json"
上述命令是經過 _bulk API 將 account.json 的內容插入 bank 索引中,type 爲 _doc
# account.json的內容:{"index":{"_id":"1"}}
{"account_number":1,"balance":39225,"firstname":"Amber","lastname":"Duke","age":32,"gender":"M","address":"880 Holmes Lane","employer":"Pyrami","email":"amberduke@pyrami.com","city":"Brogan","state":"IL"}...# 導入完成後能夠看到 bank 索引已存在 1000 條數據GET bank/_search
查詢數據 API
任務:查詢全部數據,根據 account_number 字段升序排序
URI Search 方式
GET /bank/_search?q=*&sort=account_number:asc&pretty
Request Body Search 方式
GET /bank/_search
{ "query": { "match_all": {} }, "sort": [
{ "account_number": "asc" }
]
}
結果
{ "took": 41, "timed_out": false, "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0
}, "hits": { "total": 1000, "max_score": null, "hits": [
{ "_index": "bank", "_type": "account", "_id": "0", "_score": null, "_source": { "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"
}, "sort": [ 0
]
}...
]
}
}
各個參數意思:
took:本次查詢耗費的時間(單位:毫秒)
timed_out:是否超時
_shards:本次查詢搜索的 shard 的數量,包括成功的和失敗的
hits:查詢結果
hits.total:匹配的文檔數量
hits.hits:匹配的文檔,默認返回10個文檔
hits.sort:排序的值
_score:文檔的得分
hits.max_score:全部文檔最高的得分
簡要介紹 Query DSL
這個Elasticsearch提供的基於 json 的查詢語言,咱們經過一個小任務來了解一下
任務要求:
查詢 firstname 中爲 "R" 開頭,年齡在 20 到 30 歲之間的人物信息
限制返回的字段爲 firstname,city,address,email,balance
根據年齡倒序排序,返回前十條數據
對 firstname 字段進行高亮顯示
同時求全部匹配人物的 平均balance
GET bank/_search
{ "query": { "bool": { "must": [
{ "match_phrase_prefix": { "firstname": "R"
}
}
], "filter": { "range": { "age": { "gte": 20, "lte": 30
}
}
}
}
}, "from": 0, "size": 10, "sort": [
{ "age": { "order": "desc"
}
}
], "_source": [ "firstname", "city", "address", "email", "balance"
], "highlight": { "fields": { "firstname": {}
}
}, "aggs": { "avg_age": { "avg": { "field": "balance"
}
}
}
}
其中:
query 部分能夠寫各類查詢條件
from, size 設置要返回的文檔的起始序號
sort 設置排序規則
_source 設置要返回的文檔的字段
highlight 設置高亮的字段
aggs 爲設置聚合統計規則
更多查詢示例
match_all 查詢 bank 索引全部文檔
GET /bank/_search
{ "query": { "match_all": {}
}, "size": 2}
match 全文搜索,查詢 address 字段值爲 mill lane 的全部文檔
GET /bank/_search
{ "query": { "match": { "address": "mill lane"
}
}
}
match_phrase 短語匹配
GET /bank/_search
{ "query": { "match_phrase": { "address": "mill lane"
}
}
}
note: match 和 match_phrase 的區別:
match 中會分詞,將 mill lane 拆分爲 mill 和 lane, 實際查詢 address 中有 mill 或者 lane 的文檔
match_phrase:將 mill lane 做爲一個總體查詢,實際查詢 address 中有 mill lane 的文檔
布爾查詢(多條件查詢)
GET /bank/_search
{ "query": { "bool": { "must": [
{ "match": { "age": "40" } }
], "must_not": [
{ "match": { "state": "ID" } }
]
}
}
}
布爾查詢-過濾 查詢 bank 索引中 balance 值在 20000 到 30000 之間的文檔
GET /bank/_search
{ "query": { "bool": { "must": { "match_all": {} }, "filter": { "range": { "balance": { "gte": 20000, "lte": 30000
}
}
}
}
}
}
聚合查詢 對全部文檔進行聚合,state 值相同的分到同一個桶裏,分桶結果命名爲 group_by_state ,再對每一個桶裏的文檔的 balance 字段求平均值,結果命名爲 average_balance,經過設置 size 的值爲0,不返回任何文檔內容
GET /bank/_search
{ "size": 0, "aggs": { "group_by_state": { "terms": { "field": "state.keyword"
}, "aggs": { "average_balance": { "avg": { "field": "balance"
}
}
}
}
}
}
分別計算 age 值在 20~30 ,3040,4050 三個年齡段的男和女的平均存款balance
GET /bank/_search
{ "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.keyword"
}, "aggs": { "average_balance": { "avg": { "field": "balance"
}
}
}
}
}
}
}
}
更多內容請訪問個人我的博客:http://laijianfeng.org
參考文檔:
elasticsearch 官方文檔 Getting Started
慕課網 Elastic Stack從入門到實踐
本文分享自微信公衆號 - 小旋鋒(whirlysBigData)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。