ElasticSearch 學習總結
ElasticSearch 官方網站:www.elastic.co/guide/en/el…
安裝
Elastic
需要 Java 8
環境。請參考 這篇文章 來安裝 Java,可以解決環境配置的煩惱!
安裝完 Java 8
後,在終端輸入下面的命令來下載 Elastic
的壓縮包( 版本號請自行修改 )。
$ wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.5.1.zip
$ unzip elasticsearch-5.5.1.zip
$ cd elasticsearch-5.5.1/
複製程式碼
啟動
在一切準備工作(Java
安裝完畢)做好後,進入 Elastic
檔案的根目錄下,輸入下面的命令來啟動 Elastic
。
$ ./bin/elasticsearch
複製程式碼
啟動完成後,開啟瀏覽器,在位址列輸入 localhost:9200
,如果出現類似下面的資訊,則說明啟動成功。
{
"name" : "atntrTf",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "tf9250XhQ6ee4h7YI11anA",
"version" : {
"number" : "5.5.1",
"build_hash" : "19c13d0",
"build_date" : "2017-07-18T20:44:24.823Z",
"build_snapshot" : false,
"lucene_version" : "6.6.0"
},
"tagline" : "You Know, for Search"
}
複製程式碼
Ps. 推薦一個 API
請求工具 PostMan ,它可以替代瀏覽器和終端來發起 API
請求,並且可以對返回的資料進行 JSON
格式的轉換,直觀簡潔。
基本概念
Node(節點) 與 Cluster(叢集)
Elastic
本質上是一個分散式資料庫,允許多臺伺服器協同工作,同時每臺伺服器可以執行多個 Elastic
例項。每個 Elastic
例項稱為節點,一組節點稱為叢集。
Index(索引)
Elastic
中的 Index
(索引)相當於關係型資料庫中的 dataBase
(資料庫),當然也可以理解為是 table
(表)。每個 Index
的名字必須是小寫的。下面的命令可以檢視當前 Elastic
例項下的所有 Index
,包括每個 Index
的文件大小等資訊。
$ curl -X GET 'http://localhost:9200/_cat/indices?v'
複製程式碼
當然,你也可以在上面提到的 PostMan
中輸入上面命令中的路由地址來檢視。
Document(文件)
Index
中的每條資料記錄被稱為 Document
(文件)。多條 Document
構成了一個 Index
。所以說 Index
往小了看可以被當做一張表。Document
中的資料結構是以 JSON
格式表示的。
{
"auth": "Assassin",
"work": "NodeJS全棧",
"email": "告訴你才怪@qq.com",
}
複製程式碼
Type(分類)
Index
如果被看做是一個資料庫的話,那 Type
就可以看做是這個資料庫的表。注意,同一 Index
下的 Type
應該具備相似的結構(schema
),這一點是跟關係型資料庫的區別。下面的命令是列出當前 Index
下的所有 Type
。
$ curl 'localhost:9200/_mapping?pretty=true'
複製程式碼
多說一句,
ES
與關係型資料庫的各個元素的對比:
Relational DB | Database | Table | Row | Colum |
---|---|---|---|---|
ElasticSearch | Index | Type | Document | Field |
Elastic中的資料型別
這裡只列出常用的資料型別,其餘的遇見再說
-
String:字串型別,預設會被分詞。其中包括
keyword
和text
兩種子型別。keyword:儲存資料時,資料不會被分詞建立索引,可以被用來檢索過濾、排序和聚合。如:'牆體鋼結構',
keyword
會將它作為一個整體。text:儲存資料時,資料會被分詞建立索引,但如果該欄位的資料沒有分詞的必要的話,使用
text
則會浪費儲存空間,text
資料型別不能用來排序和聚合。如:'牆體鋼結構',text
會將它切分為'牆體','鋼結構'。分詞器:只針對
text
型別。git
地址為 github.com/medcl/elast… 。其作用就是將文字按照一定的規則進行切分。安裝方法:將下載的分詞外掛解壓到根目錄下的plugins
中,然後重啟Elastic
例項。 -
數字型別:
- long:長整型,64 位儲存
- integer:整型,32 位儲存
- short:短整型,16 位儲存
- byte:位元組型,8 位儲存
- double:雙精度型,64 位儲存
- float:單精度型,32 位儲存
-
其他簡單型別
- date:時間型別
- boolean:布林型別
- binary:位元組型別
-
複合型別
- array:陣列型別
- object:json 物件型別
- Array[Object]:物件陣列的巢狀型別
Index的mapping建立
Index
的建立包括了對每張表 Type
的定義。在 JavaScript
和終端中的建立方法如下:
- JavaScript
import elasticsearch from 'elasticsearch';
const esClient = new elasticsearch.Client({
host: 'localhost:9200',
log: 'error',
});
const settings = {
number_of_shards: 5,
number_of_replicas: 1,
};
const PromiseList = [
esClient.indices.create({
index: 'student',
body: {
settings, // index的一些設定
mappings: {
// type
person: {
// type 的各個欄位
properties: {
sno: {
type: 'long',
},
name: {
type: 'keyword',
},
sex: {
type: 'keyword',
},
class: {
type: 'text',
analyzer: 'ik_max_word',
search_analyzer: 'ik_max_word',
fields: {
raw: {
type: 'keyword',
ignore_above: 128,
},
},
},
register: {
type: 'date',
},
},
},
.....
},
},
}),
.....
];
PromiseList.map(p => p.catch(e => console.log(e.message)));
.....
複製程式碼
上述程式碼中,採用的是通過
Promises
來批量建立資料庫的,如果是隻建立單一的庫可以用async await
。
- 終端
$ curl -X PUT -H 'Content-Type: application/json' 'localhost:9200/student' -d '
{
mappings: {
// type
person: {
// type 的各個欄位
properties: {
sno: {
type: 'long',
},
name: {
type: 'keyword',
},
sex: {
type: 'keyword',
},
class: {
type: 'text',
analyzer: 'ik_max_word',
search_analyzer: 'ik_max_word',
fields: {
raw: {
type: 'keyword',
ignore_above: 128,
},
},
},
register: {
type: 'date',
},
},
},
},
}'
複製程式碼
上面的程式碼中,建立了一個名為 student
的 Index
,其中包括一張 person
的表,表中包含四個欄位:son
,name
,sex
,register
。
Index的刪除
講完建立,該講刪除了。刪除很簡單:
- JavaScript
import elasticsearch from 'elasticsearch';
const esClient = new elasticsearch.Client({
host: 'localhost:9200',
log: 'error',
});
Promise.all(
[
'student',
.....
].map(index =>
esClient.indices
.delete({ index })
.catch(() => console.error(`delete fail: ${index}`))
)
);
複製程式碼
上述程式碼中,採用的是通過
Promises
來批量刪除資料庫的,如果是隻刪除單一的庫可以用async await
。
- 終端
$ curl -X DELETE 'localhost:9200/student'
複製程式碼
Elastic資料查詢
Elastic
中常用的查詢方法
search, get, count, mget, msearch 等
配置檔案
import elasticSearch from 'elasticsearch';
let _client = null;
export default () => {
if (!_client) {
_client = new elasticSearch.Client('localhost:9200');
}
return _client;
};
複製程式碼
單條記錄的條件查詢
單挑記錄的條件查詢的查詢結構為一個類似 JSON
的物件
{
index: database_name,
type: table_name,
body: {
query: {
bool: {
filter: {
term: {
'field_name': value,
},
},
},
},
},
}
複製程式碼
這是一個最簡單的查詢結構
當中的 filter
屬性值為 Object | Array
, 其中 Array
為物件陣列。如 [{term: {key: value}}, ...]
。
當然,查詢不可能這麼簡單,還有其他的可新增的屬性。
term & terms 過濾查詢(匹配查詢)
term
主要用於精確匹配哪些值,比如數字,日期,布林值。一個 term
查詢結構:
{ term: { key: value } }
複製程式碼
與其類似的 terms
主要用來匹配多個條件的過濾查詢。比如
{ terms: 'tag': [ 'react', 'vue', 'angular' ] }
複製程式碼
range 過濾查詢(範圍查詢)
range
過濾允許我們按照指定範圍查詢一批資料
{
range: {
age: {
gte: 18,
lt: 28,
}
}
}
複製程式碼
範圍的關鍵字:
-
gt: 大於
-
gte: 大於等於
-
lt: 小於
-
lte: 小於等於
在查詢結構中的體現:
{
index: database_name,
type: table_name,
body: {
query: {
range: {
age: {
gte: 18,
lt: 28,
}
}
},
}
複製程式碼
range
和 term(s)
屬於同級別的屬性,所以可以作為 filter
陣列屬性的值
exists & missing 過濾
exists & missing
用於查詢記錄中是否存在或者沒有某個指定的欄位。
{
exists: {
field: 'field_value'
}
}
複製程式碼
exists & missing
和 term(s)
屬於同級別的屬性,所以可以作為 filter
陣列屬性的值
bool 過濾
bool
布林邏輯查詢,所包含的關鍵字:
-
must: 相當於 and
-
must_not: 相當於 not
-
should: 相當於 or
用法很簡單,只需替換 filter
,當然,同 filter
一樣的用法。
agg 聚合查詢
對於這一塊,語言描述上會存在一些理解上的差異。畢竟聚合這一塊還是比較龐大的,so 為了更專業還是推薦度娘吧(等我再成長一些了再來做一下總結!!)
批量條件查詢
批量條件查詢就是對一組不同的查詢條件集依次進行處理的查詢過程,猶如一個批處理。
msearch 批量條件查詢
msearch
就是將一般的條件查詢的結構體放入到一個陣列中,然後將這個陣列再作為查詢結構體。
{
body: [
{ index: database_1, type: table_1 },
{
query: {
term: { field: value },
},
},
{ index: database_2, type: table_2 },
{
query: {
bool: {
must: {
term: {
field: value,
},
},
filter: [
{ term: { field: value } },
{ term: { field: value } },
],
},
},
},
}
複製程式碼
從上面的結構體中可以看出,msearch
的查詢結構體是吃從下標0開始,相鄰兩個元素作為一個單一查詢結構體的陣列結構。
mget 批量ID查詢
這個方法適用於已知多個記錄ID的批量查詢
{
index: database,
type: table,
body: {
ids,
},
}
複製程式碼
其中 ids
為陣列