Elasticsearch 快速開始

本文首發於個人博客,若是以爲有用,歡迎點贊收藏。html

前言

本文非徹底直譯譯文,主要參考的的是 elasticsearch 6.5 版的官網文檔 Getting Started,能夠把這篇文章理解爲我的學習筆記,我力求詳略得當吧。node

文末會附上 Getting Started 閱讀梳理的思惟導圖。linux


爲了能更加輕鬆地進入 elasticsearch 的世界,本文將先從基礎角度給介紹了 es 的使用。git

什麼是 elasticsearch

Elasticsearch 是一款開源的全文搜索與分析引擎,它擁有高擴展、大容量數據的存儲和處理特性,有着近乎實時的處理效果。elasticsearch 的使用場景仍是比較多的,好比 APP 的搜索服務、ELK 實現日誌收集與分析、BI 商業智能等。github

本文會逐步引導你們進入 elasticsearch 的世界,初步窺探它的使用。相關內容涉及以下:sql

  • 瞭解 elasticsearch 的一些基礎但很是核心的概念,好比集羣、節點、索引、分片和副本;
  • 學會 elasticsearch 安裝與啓動,同時爲了便於測試,順帶也介紹了 Kibana 的安裝啓動;
  • 探索集羣,介紹集羣涉及的一些基礎操做,好比健康狀態檢查、集羣節點檢查,索引建立等;
  • 更新數據,包括如何進行文檔替換、更新,以及如何進行刪除,最後經過批處理能夠將多個操做組合起來;
  • 數據探索,主要是與搜索和聚合分析相關,介紹了經常使用的一些搜索 API、Query DSL 和聚合 API 的使用;

總體上的內容仍是比較多的。數據庫

瞭解一些基礎概念

Elasticsearch 中有一些基礎但很核心的概念須要咱們提早了解,它們對咱們的學習將起到很大幫助。json

具體是哪些概念呢?windows

  • 近實時
  • 集羣
  • 節點
  • 索引
  • 類型
  • 文檔
  • 分片副本

下面咱們將逐一介紹。bash

近實時

什麼是近實時?

它表示一個文檔從被索引(存儲使文檔可搜索)到真正能被搜索之間有一個短暫的延遲,而非實時,這個延遲默認是 1 秒。固然,默認延遲能夠修改的。

集羣

集羣是節點的集合。

集羣實現了在多節點上進行大容量數據存儲和搜索的能力。每一個集羣都擁有惟一名稱,而節點正是根據集羣的名稱決定是否加入某個集羣。不一樣環境的集羣的名稱不能相同,如開發、測試、線上三套環境,集羣可分別命名爲 logging-dev、logging-test、logging-prod。

節點

節點,集羣組成的一部分,負責具體的事務處理,好比數據存儲、文檔索引、搜索執行等。節點也有惟一個名稱,若是沒有指定將隨機生成。

節點可經過配置集羣名稱,指定加入哪一個集羣,節點默認的集羣名稱是 elasticsearch。若是咱們在一個網絡環境下啓動多個節點,而且它們之間能夠相互發現,就將會自動組織一個名稱爲 elasticsearch 的集羣。

索引

索引是一系列類似文檔的集合,例如,咱們把客戶信息存放到一個索引,訂單信息存儲到另外一個索引中。索引可經過名稱識別,名稱必須小寫。當操做文檔時,咱們須要經過索引名稱指定。

索引的數量,集羣中並無限制定義索引的數量。

類型

elasticsearch 6.0 已丟棄功能,不具體介紹了。

有一點須要注意,爲與老版本兼容,該功能暫未完全移除,當前一個索引仍可設置類型,但當前只能指定一個類型。通常狀況下,咱們設置一個固定 type 便可,好比 _doc。

文檔

被索引的基礎信息單元,好比一個客戶、一件產品、或是一筆訂單。文檔可用 JSON 形式表示,它是一種很是廣泛的數據交換格式。索引中,咱們能夠存聽任意數量的文檔。

分片與副本

分片和副本是 elasticsearch 很是核心的概念。

咱們知道,elasticsearch 存儲的數據量能突破單個硬件的限制,數據處理速度有着近實時的水平。這些都和分片和副本有着很大關係。

分片實現了索引文檔分散分佈,而且每一個切片都是功能完善的,索引是獨立的,可能分佈在集羣中的任意節點。分片的重要性主要體如今使 elasticsearch 存儲容量的水平擴展和分佈式並行處理都成爲了現實。

副本提升了 elasticsearch 的容錯能力。網絡環境下,異常隨時可能發生,好比一些節點或分片從網絡中消失。一旦設置了副本,索引就會同時擁有主分片和副本分片。一旦某個分片發生異常,還有其餘分片可替代。並且,副本也能夠提升請求的處理速度,一個分片上的副本可同時並行處理多個請求。

一句話簡述,每一個索引能夠由多個分片組成,而每一個分片也能夠擁有多個副本。

介紹完了核心概念,是否已經開始蠢蠢欲動了?開始安裝本身的集羣吧。

安裝與啓動

本節主要介紹 elasticsearch 的安裝。另外,因爲要使用 kibana 的 devtools 控制檯,將也會介紹下 kibana 的安裝。

安裝 elasticsearch

首先安裝依賴,elasticsearch 是 Java 開發,6.5 版依賴 Java 8,建議安裝 Oracle JDK 1.8.0_131。Java 安裝完成後,就能夠開始安裝 elasticsearch 了。

簡單起見,咱們只介紹二進制包的安裝。

安裝過程僅僅三步搞定!

$ curl -L -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.5.4.tar.gz
$ tar -xvf elasticsearch-6.5.4.tar.gz
$ cd elasticsearch-6.5.4/bin
$ ./elasticsearch -d # -d 表示後臺啓動
複製代碼

安裝啓動完成後,可經過訪問 localhost:9200 確認下實例運行是否正常。

若是想了解 Mac 的 homebrew 安裝或 windows 下的 MSI Installer Package 安裝,可自行閱讀官方文檔

安裝 kibana

Kibana 的安裝與 elasticsearch 的不一樣,須要區別不一樣的平臺系統。本節將介紹 Mac 與 Linux 下的安裝,它們均可以經過下載對應系統的 tar 包完成。

Linux 系統,咱們以 Linux x86_64 爲例。安裝命令以下:

$ wget https://artifacts.elastic.co/downloads/kibana/kibana-6.5.4-linux-x86_64.tar.gz
$ shasum -a 512 kibana-6.5.4-linux-x86_64.tar.gz 
$ tar -xzf kibana-6.5.4-linux-x86_64.tar.gz
$ cd kibana-6.5.4-linux-x86_64/
$ ./bin/kibana
複製代碼

MacOS 系統,安裝命令以下:

$ curl -O https://artifacts.elastic.co/downloads/kibana/kibana-6.5.4-darwin-x86_64.tar.gz
$ shasum -a 512 kibana-6.5.4-darwin-x86_64.tar.gz 
$ tar -xzf kibana-6.5.4-darwin-x86_64.tar.gz
$ cd kibana-6.5.4-darwin-x86_64/ 
$ ./bin/kibana
複製代碼

若是但願 kibana 在後臺運行,能夠經過 nohup 實現。完成後,訪問 localhost:5601 下確認狀態,它會默認鏈接本地啓動的 elasticsearch 集羣。

好吧!我仍是不想介紹 Windows 下的安裝。

多節點集羣

若是但願啓動一個多節點集羣,咱們能夠修改下啓動命令,在本地同時啓動兩個節點,集羣名稱相同狀況下,它們將會自動組織成一個新的集羣。命令以下:

$ ./bin/elasticsearch -Ecluster.name=cluster_dev -Epath.data=cluster_node01 -Enode.name=node01 -Ehttp.port=9200 -d
$ ./bin/elasticsearch -Ecluster.name=cluster_dev -Epath.data=cluster_node02 -Enode.name=node02 -Ehttp.port=9201 -d
複製代碼

啓動成功後,能夠進入 kibana 的 devtool 執行 _cat/nodes?v,輸出以下:

ip        heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
127.0.0.1           29          75   6    3.31                  mdi       -      node01
127.0.0.1           33          75   6    3.31                  mdi       *      node02
複製代碼

咱們將會看到集羣中已經有了兩個節點。

探索集羣

經歷了前面幾步,elasticsearch 集羣已經安裝完成,但咱們要如何與它交流呢?其實,elasticsearch 已經提供了一套全面且功能強大的 REST API,用於與集羣交互。REST API 涉及功能包括:

  • 檢查集羣、節點和索引的健康狀況、狀態以及統計信息;
  • 管理集羣、節點、索引和元數據;
  • 針對索引的增刪改查以及搜索 API;
  • 高級搜索功能,好比分頁、排序、過濾、腳本處理、聚合等;

本節咱們將簡單介紹上面提到的部分 API。

集羣健康檢查

健康檢查可讓咱們瞭解集羣當前狀態,可經過 _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_percent
1565884060 23:47:40  cluster_dev green           2         2     22  21    0    0        0             0                  -                100.0%
複製代碼

輸出結果顯示,集羣名稱爲 cluster_dev,狀態是 green,當前集羣有 2 個節點。

先重點講講 green 究竟表明什麼意思?

首先,green 表示的是集羣的狀態,對應字段名稱是 status,共有三種狀態,分別是 green、yellow 和 red。

  • Green 表示集羣運行徹底正常(主分片和副本分片都運行正常);
  • Yellow 表示全部主分片可用,但副本沒有徹底分配;
  • Red 部分數據徹底不可用,即不管主分片和副本都非正常運做;

當集羣狀態是 red 時,仍然能夠接收處理搜索請求,但咱們須要馬上修復它。

查看集羣節點

經過 _cat/nodes,能夠列出當前集羣下的全部節點,前面在啓動一個多節點集羣時,咱們已通過了使用該 API,很少介紹了。

列出全部索引

_cat/indices?v 能列出集羣中的全部索引。說明一下,indices 是 index 的複數形式。

GET _cat/indices
複製代碼

輸出以下:

health status index    uuid                   pri rep docs.count docs.deleted store.size pri.store.size
green  open   us_tweet WXkAeMEvR0eukVOFOM1q3w   5   0          6            0     15.7kb         15.7kb
green  open   gb_user  pbOu0n0XQ96mouQ642eutQ   5   0          1            0      5.7kb          5.7kb
green  open   us_user  idxuhX0LQlekzfbjd6kB5w   5   0          1            0      5.7kb          5.7kb
green  open   gb_tweet SJTleUerT5CaO9Sl-JwIQg   5   0          6            0     15.7kb         15.7kb
複製代碼

個人本地集羣常常拿來測試,因此這裏會看到已經有不少 index,對於你剛搭建好的集羣,輸出確定就是空的。

建立索引

接下來,咱們學習下如何建立索引,直接看示例吧。嘗試建立一個名爲 "customer" 的索引,以下:

PUT customer?pretty
複製代碼

PUT 加上索引名稱便可。 customer 索引成功建立後,查看下集羣當前索引列表,以下:

GET _cat/indices
複製代碼

輸出結果以下:

health status index    uuid                   pri rep docs.count docs.deleted store.size pri.store.size
...
green  open   customer 71RYoldbQ6uXMo56t4bSog   5   1          0            0      1.1kb           460b
...
複製代碼

customer 成功建立,包含 5 個主分片和 1 個副本分片,索引中當前的文檔數量爲 0,索引狀態爲 green。

索引的狀態和集羣同樣,也是 green、yellow 和 red 這 3 個值,而且含義與集羣狀態相似。green 是全功能正常,yellow 表示副本未徹底分配,red 表示部分主分片不可用。咱們能夠測試一下,中止集羣中的一個節點,這時 customer 的狀態將會立刻切換爲 yellow 狀態。

索引和查詢文檔

在 elasticsearch 中,"索引" 這個名詞經常會搞暈咱們。通常講到索引,主要是指它的名詞含義,好比咱們說,建立一個 customer 索引。但有時,它又是動詞,好比咱們在增長和更新文檔時,常會說索引一個文檔,在這種狀況下,能夠把它理解爲存儲文檔並使其可搜索。

那如何索引一個文檔呢?好比,索引一個 ID 爲 1 的 customer 文檔到 customer 索引中,以下。

PUT /customer/_doc/1?pretty
{
  "name": "John Doe"
}
複製代碼

響應返回:

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

結果代表,咱們已經成功建立一個 ID 爲 1 的文檔。從這裏也能看出,在索引一個文檔以前,並不要求咱們明確建立索引 customer,若是 customer 索引不存在,elasticsearch 將會自動幫助咱們建立索引。

檢索剛纔索引的文檔。

GET /customer/_doc/1?pretty
複製代碼

響應以下:

{
  "_index" : "customer",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "found" : true,
  "_source" : { "name": "John Doe" }
}
複製代碼

found 字段代表,咱們已經成功檢索到了一個 ID 爲 1 的文檔。_source 中的內容是檢索文檔的完整內容。

刪除索引

讓咱們刪除掉剛剛建立的索引。

DELETE /customer?pretty
複製代碼

如此,咱們就成功刪除了以前建立的 customer。若是不肯定,可使用 GET _cat/indices 檢查下。

文檔 API

回顧下前面介紹的那些 API,咱們從新再走一遍。

PUT /customer
PUT /customer/_doc/1
{
  "name": "John Doe"
}
GET /customer/_doc/1
DELETE /customer
複製代碼

仔細觀察上面的命令,你可能會發現一個比較通用的模式,以下:

<HTTP Verb> /<Index>/<Type>/<ID>
複製代碼

這個模式在 elasticsearch 中很是廣泛,記住它,這將對 elasticsearch 學習之旅將會很是有幫助。

更新數據

區別於傳統關係型數據庫的實時性特色,elasticsearch 是近實時的,也就是說,在文檔被 create/update/delete 與搜索結果中出現之間將會有 1 秒的延遲。

文檔替換

建立和替換文檔本質上都屬於索引文檔,於是,咱們以前用來建立文檔的命令一樣適用於文檔替換。

由於 customer 索引重建過,咱們從新建立一個 ID 爲 1 的文檔。以下:

PUT /customer/_doc/1?pretty
{
  "name": "John Doe"
}
複製代碼

一樣的命令便可實現文檔更新,咱們只須要傳遞不一樣的文檔內容便可,以下:

PUT /customer/_doc/1?pretty
{
  "name": "Jane Doe"
}
複製代碼

將 ID 爲 1 的文檔中 name 由 Johh Doe 更新爲 Jane Doe。若是指定 ID 文檔不存在,將會建立新的文檔,不然更新當前文檔。

好比,ID 爲 2 的文檔不存在,經過以下命令建立。

PUT /customer/_doc/2?pretty
{
  "name": "Jane Doe"
}
複製代碼

索引文檔時,ID 不是必須的,若是不指定,elasticsearch 會自動爲這個文檔指定一個隨機的 ID,並做爲響應的一部分返回給你。

示例以下:

POST /customer/_doc?pretty
{
  "name": "Jane Doe"
}
複製代碼

這種狀況下,咱們須要使用 POST 代替 PUT 提交請求。

響應結果:

{
  "_index": "customer",
  "_type": "_doc",
  "_id": "Z-RnpGwBe6KTDC6t3MGV",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 1,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 0,
  "_primary_term": 1
}
複製代碼

上面能夠看到 elasticsearch 爲咱們生成的文檔 ID,Z-RnpGwBe6KTDC6t3MGV。

更新文檔

說完文檔的索引和替換,咱們再來談談文檔的更新。提早說明,elasticsearch 並不是真的去更新文檔,它的更新操做與替換相似,包含刪除舊文檔和索引新文檔兩個操做。

示例演示,更新前面建立的 ID 爲 1 的文檔,更新 name 字段爲 Jane Doe。

POST /customer/_doc/1/_update?pretty
{
  "doc": { "name": "Jane Doe" }
}
複製代碼

示例 2,更新 name 爲 Jane Doe 的同時,增長一個字段 age。

POST /customer/_doc/1/_update?pretty
{
  "doc": { "name": "Jane Doe", "age": 20 }
}
複製代碼

示例 3,使用腳本更新文檔,好比將 ID 爲 1 的文檔的字段 age 加 5。

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

上面的例子,ctx._source 表示的是咱們將要更新的文檔。這裏是經過指定 ID 的方式查詢要更新的文檔,elasticsearch 也能夠像 SQL 同樣,經過複雜查詢實現更新。

刪除文檔

刪除文檔最簡單直接,HTTP 方法換成 DELETE,指定文檔 ID 便可。以下:

DELETE /customer/_doc/2?pretty
複製代碼

和更新相似,刪除也能夠根據查詢結果執行刪除,API 是 _delete_by_query。若是是刪除索引中的全部文檔,直接刪除索引更直接點。

批處理

通過前面的學習,咱們已經瞭解了 elasticsearch 一些基礎 API 的使用,如文檔的索引、更新、刪除。這一小節介紹一個新的 API,_bulk API,它支持將多個操做打包成一個請求,實現批處理。這樣能夠更加高效的執行操做,也能減小網絡傳遞次數。

一個快速入門案例,以下:

POST /customer/_doc/_bulk?pretty
{"index":{"_id":"1"}}
{"name": "John Doe" }
{"index":{"_id":"2"}}
{"name": "Jane Doe" }
複製代碼

索引了 2 個文檔,一個文檔 ID 1,name 爲 John Doe,另外一個文檔 ID 2,name 爲 Jane Doe。

再看一個案例,以下:

POST /customer/_doc/_bulk?pretty
{"update":{"_id":"1"}}
{"doc": { "name": "John Doe becomes Jane Doe" } }
{"delete":{"_id":"2"}}
複製代碼

批處理包含 2 個操做,更新 ID 爲 1 文檔的 name 字段和刪除 ID 爲 2 的文檔。

批處理中的一個操做失敗並不會致使整個 bulk API 處理失敗,若是一個操做失敗,剩下來的其餘操做仍會繼續執行。bulk API 處理完成後,響應結果中會包含每一個操做的處理結果。

數據探索

本節內容主要涉及兩個方面:搜索與分析。

數據

搜索分析不可缺乏數據,咱們將使用 elastic 官方提供的數據樣本,相對而言,應該比本身的生成更符合真實場景。

一個文檔,示例以下:

{
    "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"
}
複製代碼

官方的數據是用工具隨機生成的,工具地址。有興趣,能夠設置本身的數據生成規則。

開始數據加載以前,要先下載數據,下載地址

$ 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"
複製代碼

查看索引信息

$ curl "localhost:9200/_cat/indices?v"
複製代碼

響應以下:

health status index uuid                   pri rep docs.count docs.deleted store.size pri.store.size
green  open   bank  FFcSux-ETmmUlMJNBCEyqA   5   1       1000            0      957kb        482.3kb
複製代碼

能夠看出,咱們已經爲 bank 成功索引了 1000 個文檔。

搜索 API

開始嘗試一些簡單的搜索。有兩種基本的搜索方式:

  • URI Search,一般 URI 參數指定搜索參數。
  • Request Body,在請求內容包含在請求體中發送。

相對而言,Request Body 方式更靈活,包含了所有的搜索支持。而 URI Search 主要在測試時使用,比較方便。

搜索請求經過 _search 執行。一個示例,經過搜索返回 bank 索引中的全部文檔。

GET /bank/_search?q=*&sort=account_number:asc&pretty
複製代碼

URI Search 方式實現搜索,經過 q=* 執行匹配所有文檔,sort=account_number:asc 指定排序方式。

響應以下:

{
  "took" : 63,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 1000,
    "max_score" : null,
    "hits" : [ {
      "_index" : "bank",
      "_type" : "_doc",
      "_id" : "0",
      "sort": [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"}
    }, ...
    ]
  }
}
複製代碼

結果中的各個參數函數以下:

  • took 表示搜索執行時間
  • timed_out 搜索是否超時
  • _shards 多少分片參與搜索,以及成功與失敗的狀況如何。
  • hits 搜索結果
  • hits.total 匹配搜索條件的文檔數量
  • hits.hits.sort 排序
  • hits.hits._score 和 max_score,相關度得分,指定排序,字段會被忽略。

經過 Reuqest Body 方式執行與上面相同的操做,以下:

GET /bank/_search
{
  "query": { "match_all": {} },
  "sort": [
    { "account_number": "asc" }
  ]
}
複製代碼

咱們下面主要介紹 Request Body 的使用,畢竟它更增強大。

DSL 介紹

DSL,全稱 Domain Special Language, 即特定領域語言,elasticsearch 制定了一套 JSON 風格的 DSL 語言。它支持的功能很是全面,剛學習它時,會讓咱們產生一種恐懼,由於它真的很難。咱們能夠先從一些簡單的例子看起。

查詢全部文檔,以下:

GET /bank/_search
{
  "query": { "match_all": {} }
}
複製代碼

解剖下請求體。query 定義查詢語句,match_all 就是咱們將會執行的查詢語句,表示匹配索引中的全部文檔。

執行上面的查詢語句默認只會返回 10 條文檔,咱們能夠經過指定 size 參數改變默認獲取文檔數量。以下:

GET /bank/_search
{
  "query": { "match_all": {} },
  "size": 1
}
複製代碼

經過 from 和 size 能夠實現分頁效果,以下:

GET /bank/_search
{
  "query": { "match_all": {} },
  "from": 10,
  "size": 10
}
複製代碼

from 用於指定文檔偏移的開始位置,至關於 SQL 中的 offset。

文檔默認根據搜索相關度得分排序,不過咱們這裏是默認匹配所有,因此文檔的相關度得分都是1。除了相關度排序,還能夠按其餘字段,好比 balance 字段。以下:

GET /bank/_search
{
  "query": { "match_all": {} },
  "sort": { "balance": { "order": "desc" } }
}
複製代碼

搜索查詢語句

繼續看下搜索返回文檔字段,默認狀況下,搜索將會返回文檔的全部字段內容。咱們可經過 _source 指定只返回部份內容。

GET /bank/_search
{
  "query": { "match_all": {} },
  "_source": ["account_number", "balance"]
}
複製代碼

如此,搜索將只返回 account_numberbalance 兩個字段。 瞭解的 SQL 的朋友能夠將其與 SELECT 指定列類比。

繼續看查詢部分吧!

前面,經過 match_all 查詢匹配了所有文檔。如今,咱們再引入一個新的查詢語句,match,它是基於一個字段的查詢。

查詢 account_number 爲 20 的文檔。示例以下:

GET /bank/_search
{
  "query": { "match": { "account_number": 20 } }
}
複製代碼

查詢 address 包含 mill 的文檔。示例以下:

GET /bank/_search
{
  "query": { "match": { "address": "mill" } }
}
複製代碼

查詢 address 包含 mill 或 lane 的文檔。示例以下:

GET /bank/_search
{
  "query": { "match": { "address": "mill lane" } }
}
複製代碼

match 基於分詞查詢,2 個查詢單詞是 or 的關係。若是咱們就要搜索 "mill lane" 呢? 這時可使用 match_pharse。示例以下:

查詢 address 包含 "mill lane" 的文檔。示例以下:

GET /bank/_search
{
  "query": { "match_phrase": { "address": "mill lane" } }
}
複製代碼

繼續介紹 bool 查詢,它容許咱們將上面這些基礎查詢組合造成一個複合查詢。好比,查詢同時包含 "mill" 和 "jane" 的文檔。

示例以下:

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

例子中的 bool must 表示文檔必須同時知足兩個 must 條件。若是是隻要知足一個條件便可,咱們可使用 bool should,示例以下:

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

若是要求二者必須不知足,咱們可使用 bool must_not,示例以下:

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

bool 查詢中還能夠將上面的這幾種查詢同時組合起來,同時包含 must、must_not 和 should。

示例以下:

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

注意一點,若是是 must、must_not 和 should 組合時,should 就缺乏了必須知足一個纔算匹配的限制,這時,咱們能夠經過 minimum_should_match 指定 should 匹配個數。

更復雜的,bool 查詢中還能夠包含其餘的 bool 查詢。這裏先不介紹了。

過濾語句

談到過濾以前,咱們就不得不提文檔相關度評分,相關度評分是用於衡量搜索語句與文檔的匹配程度的一個指標。前面已經提過的查詢語句都會參與到這個指標的計算。

但有時,查詢僅僅是爲了過濾一些不知足條件的文檔,咱們並不但願它們也參與到相關度評分的計算中,由此,咱們並引入了 filter。

前面介紹的 bool 查詢中便支持 filter 功能。它能夠在不影響相關度評分的狀況下,實現文檔過濾。以下:

GET /bank/_search
{
  "query": {
    "bool": {
      "must": { "match_all": {} },
      "filter": {
        "range": {
          "balance": {
            "gte": 20000,
            "lte": 30000
          }
        }
      }
    }
  }
}
複製代碼

bool 查詢中包含了 must 和 filter 兩部分。filter 部分經過 range query 實現只查詢 blanace 知足指定區間的文檔,must 中的 match_all 實現所有文檔返回。

除了上面介紹的查詢,如 match_all、match、bool、range,elasticsearch 還有不少其它查詢可用,這裏不詳細介紹了。只要掌握了前面的知識,咱們已經徹底能夠照貓畫虎。

聚合功能

利用 elasticsearch 的聚合能力,咱們能夠實現分組統計,能夠和 SQL 的 GROUP BY 分組和聚合函數類比。搜索和聚合都是經過 _search 請求實現,同一個請求可同時處理搜索與聚合的請求。這樣也能夠幫助咱們節省必要的網絡帶寬。

一個例子,按銀行卡帳號狀態(即 state)分組。默認是返回 top 10。以下:

GET bank/_search
{
  "size": 0,
  "aggs": {
    "group_by_state": {
      "terms": {
        "field": "state.keyword"
      }
    }
  }
}
複製代碼

如何 SQL 呢?以下:

SELECT state, COUNT(*) FROM bank GROUP BY state ORDER BY COUNT(*) DESC LIMIT 10;
複製代碼

響應以下:

{
  "took": 29,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped" : 0,
    "failed": 0
  },
  "hits" : {
    "total" : 1000,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "group_by_state" : {
      "doc_count_error_upper_bound": 20,
      "sum_other_doc_count": 770,
      "buckets" : [ {
        "key" : "ID",
        "doc_count" : 27
      }, {
        "key" : "TX",
        "doc_count" : 27
      }, {
        "key" : "AL",
        "doc_count" : 25
      }, {
        "key" : "MD",
        "doc_count" : 25
      }, {
        "key" : "TN",
        "doc_count" : 23
      }, {
        "key" : "MA",
        "doc_count" : 21
      }, {
        "key" : "NC",
        "doc_count" : 21
      }, {
        "key" : "ND",
        "doc_count" : 21
      }, {
        "key" : "ME",
        "doc_count" : 20
      }, {
        "key" : "MO",
        "doc_count" : 20
      } ]
    }
  }
}
複製代碼

從上面能夠看出,ID 爲 Idaho 的數量爲 27,緊接着是 TX 數量 27,而後是 AL 共 25 個。上面設置 size 爲 0,是爲隱藏搜索結果內容,僅僅顯示聚合結果。

咱們能夠在前面的聚合結果的基礎上,計算 top 10 的帳戶餘額平均值。以下:

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

在 group_by_state 中加入子聚合 average_balance,同時在 group_by_state 中,經過 order 配置實現了按 balance 平均值大小排序的需求。

下面這個例子演示瞭如何按年齡區間分組,好比 20-2九、30-39 和 40-49,並在基礎上,繼續按性別分組。最後,計算各個分組 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"
              }
            }
          }
        }
      }
    }
  }
}
複製代碼

例子中有兩個分組 group_by_age 和 group_by_gener 以及一個聚合計算 average_balance。

總的來講,上面的例子仍是比較循環漸進的。但主要仍是集中在使用層面,並無太多細節的介紹。若是想了解更多與聚合相關的內容,可自行查詢官方文檔。

總結

Elasticsearch 能夠說是一款即簡單又複雜的產品。本文只是簡單介紹了它的一些基礎,並初步體驗了下它的使用。到此,僅僅算是開啓了一扇門,elasticsearch 的使用遠沒有那麼簡單。

再接再礪吧!朋友!

附錄

Getting Started

Basic Concepts

Installation

Exploring Your Cluster

Modify Your Data

Exploring Your Data


波羅學的公衆號
相關文章
相關標籤/搜索