ElasticSearch初體驗

須要明白的問題

  1. 什麼是倒排索引?它的組成是什麼?node

  2. 常見的相關性算分方法有哪些?linux

  3. 爲何查詢語句沒有返回預期的文檔?git

  4. 經常使用的數據類型有哪些?Text和Keyword的區別是什麼?es6

  5. 集羣是如何搭建起來的?是如何實現故障轉移的?github

  6. 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:

  1. 在建立索引的時候若是沒有配置索引Mapping,一個索引默認有5個shard和1個副本,一個索引總共有10個shard(算上副本shard)

  2. 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:

  1. customer 爲索引名,_doc 爲type,1爲文檔_id,須要注意的是:在es6.x建議索引的type值固定爲_doc,在以後的版本將刪除type了;文檔id若不指定,es會自動分配一個_id給文檔

  2. 插入文檔後,查看索引信息GET /_cat/indices?v能夠看到多了 customer 的索引信息

  3. 文檔結果,_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索引下id3的文檔# 2. delete刪除 customer索引下id3的文檔# 3. create建立 customer索引下id3的文檔# 4. update更新 customer索引下id3的文檔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:

  1. 批量查詢用的是 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 字段升序排序

  1. URI Search 方式

GET /bank/_search?q=*&sort=account_number:asc&pretty
  1. 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 的查詢語言,咱們經過一個小任務來了解一下

任務要求:

  1. 查詢 firstname 中爲 "R" 開頭,年齡在 20 到 30 歲之間的人物信息

  2. 限制返回的字段爲 firstname,city,address,email,balance

  3. 根據年齡倒序排序,返回前十條數據

  4. 對 firstname 字段進行高亮顯示

  5. 同時求全部匹配人物的 平均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

參考文檔:

  1. elasticsearch 官方文檔 Getting Started

  2. 慕課網 Elastic Stack從入門到實踐


本文分享自微信公衆號 - 小旋鋒(whirlysBigData)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索