Elasticsearch 開箱指南

  • 2020 年 2 月 19 日
  • 筆記

內容概要

  • ES 基礎介紹,重點是其中的核心概念。
  • 基礎 API 實踐操作。

1. 基礎介紹

Elasticsearch (ES) 是一個資料庫,提供了分散式的、准實時搜索和分析。

基於 Apache Lucene,可以操作結構化數據、非結構化數據、數字類型數據、地理空間數據。

數據存儲使用鬆散結構的 JSON 文檔。

主要特性

  • 輕量快速的全文搜索。
  • 安全分析和基礎設施監控。
  • 支援海量規模,數千台伺服器、PB級數據量。
  • 可以集成可視化數據分析工具,用於例如應用性能分析、日誌監控、基礎設施度量指標監控。
  • 可以用於機器學習,對數據實時進行自動化模型處理。

核心概念

  • Index 索引

關係資料庫中的表,存儲文檔。

6.0.0 版本之前,一個索引中可以存放不同類型的文檔,例如 Car 和 Bike 這2種文檔可以在一個索引中。

6.0.0 版本之後,不可以了,需要為每種類型的文檔建立不同的索引。

  • Documents 文檔

關係資料庫中的 行。

每個文檔有一個唯一 _id。

  • Fields 欄位

關係資料庫中的 列。

  • 數據類型

1)字元串

有2種類型:text 和 keyword。

text 用戶存儲產品描述、文章內容之類的文本,可以根據關鍵字在其中查找。

ES 會把內容解析成一個字元串列表,然後創建倒排索引,描述每個單詞都在哪些文檔中出現了。

例如一個文檔有一個欄位 「Description」,值為 「This phone has dual sim capability」。

這個值會被解析為一個列表:

[「this」, 「phone」, 「has」, 「dual」, 「sim」, 「capability」]

倒排索引中,會指出每個詞所在的文檔列表,如:

「this」 -> doc_1,doc_3

Keyword 用於存儲用戶名、郵件地址、郵編這類的明確的內容。

這類內容不會被分割解析,適用於精確匹配。

2)數字

存儲例如標識碼、百分比、電話號等。

支援:long, integer, short, byte, double, float。

3)日期

形式包括:「2015/01/01 12:10:30」 此類的字元串、微秒級 long 型數字、秒級 integer 型數字。

內部使用 UTC long 型存儲。

4)布爾

5)IP

6)嵌入式

一個屬性可以是一個 JSON 數組。

例如:

{     "name":"ABC United",     "homeGround":"Old Trafford",     "players":[        {           "firstName":"James",           "lastName":"Cohen",           "position":"Goal Keeper"        },        {           "firstName":"Paul",           "lastName":"Pogba",           "position":"Midfielder"        }     ]  }

對於嵌入類型,每個數組對象都會被作為一個隱藏文檔進行索引。

7)多類型

例如有一個欄位 「student_name」,我們希望可以通過部分匹配的方式進行查找,也希望通過完全匹配的方式查找。

這就相當於同時有2種類型:text和 keyword。

可以這樣設置:

{     "student_name":{        "type":"text",        "fields":{           "keyword":{              "type":"keyword"           }        }     }  }
  • Mapping

用於定義一個索引的 schema。

定義索引中有哪些欄位、欄位類型,配置類型相關的元數據。

  • Setting

通過 Setting 可以自定義一些索引的行為,還允許我們自定義分析器和標準化器,以分析索引的不同文本欄位。

重要的 Setting 例如:

1)number_of_shards:定義索引分片數量,默認為 1。

2)number_of_replicas:定義分片的副本數量,默認 1。

3)refresh_interval:用於指定文檔索引的時間與可供搜索的時間之間的間隔,默認 1秒。

  • Shard 分片

一個分片是一個 Lucene 實例,是一個被 ES 自動管理的工作單元。

我們只需要指定分片及其副本的數量,無需對分片進行操作。

ES 自動在所有節點中分布所有分片,當節點故障時,會把分片移到其他節點,當有新節點添加進來時,也會自動把一些分片移過來。

  • Replicas 副本

主分片的拷貝,副本的作用:

1)當主分片故障後,其副本可以提升為主分片。

2)主分片及其副本都可以處理查詢請求,可以提升性能。

  • Aliases 別名

用於指定索引或索引集的替代名稱。

當我們想從多個索引中獲取文檔時非常有用。

  • Template 模板

用戶對多個索引指定通用的 mapping 和 Setting。

每當創建與模板中定義的特定模式匹配的新索引時,模板將應用於該索引。

創建索引時特別定義的任何 mapping/Setting 都將優先於模板中的定義。

2. API 操作

測試環境搭建

使用的 ES 版本為 7.5.1。

下面使用docker啟動一個單節點環境:

docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.5.1

測試:

$ curl -X GET "localhost:9200/_cat/nodes?v&pretty"  ip         heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name  172.17.0.2            7          97   2    0.96    0.61     0.25 dilm      *      245e340eba97    $ curl localhost:9200  {    "name" : "245e340eba97",    "cluster_name" : "docker-cluster",    "cluster_uuid" : "mq_bxY5zTjCpmJU0xOLSbA",    "version" : {      "number" : "7.5.1",      "build_flavor" : "default",      "build_type" : "docker",      "build_hash" : "3ae9ac9a93c95bd0cdc054951cf95d88e1e18d96",      "build_date" : "2019-12-16T22:57:37.835892Z",      "build_snapshot" : false,      "lucene_version" : "8.3.0",      "minimum_wire_compatibility_version" : "6.8.0",      "minimum_index_compatibility_version" : "6.0.0-beta1"    },    "tagline" : "You Know, for Search"  }

參考文檔:

https://www.elastic.co/guide/en/elasticsearch/reference/7.5/docker.html

實踐操作

  • 創建索引
curl -X PUT "localhost:9200/traveler?pretty" -H 'Content-Type: application/json' -d'  {     "settings":{        "number_of_shards":5,        "number_of_replicas":2     },     "mappings":{        "properties":{           "name":{              "type":"keyword"           },           "age":{              "type":"integer"           },           "background":{              "type":"text"           },           "nationality":{              "type":"keyword"           }        }     }  }  '
  • 插入文檔
curl -X PUT "localhost:9200/traveler/_doc/1?pretty" -H 'Content-Type: application/json' -d'  {     "name":"John Doe",     "age":"23",     "background":"Born and brought up in California. Engineer by profession. Loves to cook",     "nationality":"British"  }  '
  • 讀取文檔
curl -X GET "localhost:9200/traveler/_doc/1?pretty"
  • 刪除文檔
curl -X DELETE "localhost:9200/traveler/_doc/1?pretty"
  • 刪除索引
curl -X DELETE "localhost:9200/traveler?pretty"
  • 所有索引列表
curl -X GET "localhost:9200/_cat/indices"
  • 查看集群健康情況
curl -X GET "localhost:9200/_cat/health?v"
  • 查看某個索引的資訊
# mapping + setting  curl -X GET "localhost:9200/traveler?pretty"    # mapping  curl -X GET "localhost:9200/traveler/_mapping?pretty"    # setting  curl -X GET "localhost:9200/traveler/_settings?pretty"
  • 為索引設置別名
curl -X POST "localhost:9200/_aliases" -H 'Content-Type: application/json' -d'  {     "actions":[        {           "add":{              "index":"traveler",              "alias":"read_alias"           }        }     ]  }  '
  • 獲取索引中的所有文檔
curl -X GET "localhost:9200/traveler/_search?pretty"

結果中的關鍵項: took - 此次查詢耗時,毫秒。 timed_out - 查詢是否超時。 _shards - 查詢了分片的情況,如一共查詢了幾個分片、成功了幾個。 hits - 查詢結果。 hits.total - 結果文檔數。 hits.hits - 結果數組,默認只顯示前10個文檔。 hits.max_score - 匹配度最高的文檔的分值。 hits.hits._score - 此文檔匹配度分值。

  • 獲取所有中的文檔總數
curl -X GET "localhost:9200/traveler/_count?pretty"
  • 匹配查詢
curl -X GET "localhost:9200/traveler/_search?pretty" -H 'Content-Type: application/json' -d'  {     "query":{        "match":{           "background":"brought up California Loves cook"        }     }  }  '

匹配條件是 "background",其值會被處理為數組:[「brought」, 「up」, 「california」, 「loves」, 「cook」]。

只要其中的某一個與文檔中的 "background" 值相匹配,文檔就會被返回。

  • term 查詢
curl -X GET "localhost:9200/traveler/_search?pretty" -H 'Content-Type: application/json' -d'  {     "query":{        "term":{           "name":{              "value":"John Doe"           }        }     }  }  '

這用於獲取在提供的欄位中包含確切術語的文檔。

適用於 keyword, numeric, date, boolean 類型的欄位。

  • terms 查詢
curl -X GET "localhost:9200/traveler/_search?pretty" -H 'Content-Type: application/json' -d'  {     "query":{        "terms":{           "name":[              "John Doe",              "Jack Ripper",              "Buzz Aldrin"           ]        }     }  }  '

類似 IN 查詢,匹配一個或多個。

  • 前綴匹配查詢
curl -X GET "localhost:9200/traveler/_search?pretty" -H 'Content-Type: application/json' -d'  {     "query":{        "prefix":{           "name":"Joh"        }     }  }  '
  • 正則查詢
curl -X GET "localhost:9200/traveler/_search?pretty" -H 'Content-Type: application/json' -d'  {     "query":{        "regexp":{           "name":{              "value":"J.*e"           }        }     }  }  '
  • 單次多查詢

在一個請求中執行多個查詢操作。

curl -X GET "localhost:9200/_msearch?pretty" -H 'Content-Type: application/x-ndjson' -d'  {"index":"traveler"}  {"query":{"terms":{"name":["John Doe","Jack Ripper","Barack Obama"]}}}  {}  {"query":{"prefix":{"name":"Buzz"}}}  {"index":"traveler"}  {"query":{"match_all":{}}}  '

Tags: