一. ES安裝
1.1 本地安裝
下載對應(yīng)系統(tǒng)的安裝包 下載地址
-
前臺啟動
cd elasticsearch-<version> ./bin/elasticsearch
-
作為守護(hù)進(jìn)程后臺啟動
cd elasticsearch-<version> ./bin/elasticsearch -d
-
測試是否啟動成功
curl 'http://localhost:9200/?pretty'
{ "name" : "Meltdown", "cluster_name" : "elasticsearch", "cluster_uuid" : "ysXZW5y_TNmPh-oKLJYEvg", "version" : { "number" : "2.4.3", "build_hash" : "d38a34e7b75af4e17ead16f156feffa432b22be3", "build_timestamp" : "2016-12-07T16:28:56Z", "build_snapshot" : false, "lucene_version" : "5.5.2" }, "tagline" : "You Know, for Search" }
1.2 docker安裝
- 基本命令
參考地址docker run -d -p 9200:9200 -p 9300:9300 -v /Users/lay/dockerspace/elasticsearch/master/config:/usr/share/elasticsearch/config -v /Users/lay/dockerspace/elasticsearch/master/data:/usr/share/elasticsearch/data --name=elasticsearch-test elasticsearch -Des.node.name="TestNode"
二. 基本概念
- 索引(名詞)
一個 索引 類似于傳統(tǒng)關(guān)系數(shù)據(jù)庫中的一個 數(shù)據(jù)庫 获三,是一個存儲關(guān)系型文檔的地方,是ES對邏輯數(shù)據(jù)的邏輯存儲,索引的結(jié)構(gòu)是為快速有效的全文檢索做準(zhǔn)備既荚。 索引 (index) 的復(fù)數(shù)詞為 indices 或 indexes 。
- 索引(動詞)
索引一個文檔 就是存儲一個文檔到一個 索引 (名詞)中以便它可以被檢索和查詢到。這非常類似于 SQL 語句中的 INSERT 關(guān)鍵詞,除了文檔已存在時新chaj文檔會替換舊文檔情況之外怕品。
- 倒排索引
倒排索引源于實(shí)際應(yīng)用中需要根據(jù)屬性的值來查找記錄。這種索引表中的每一項(xiàng)都包括一個屬性值和具有該屬性值的各記錄的地址巾遭。由于不是由記錄來確定屬性值肉康,而是由屬性值來確定記錄的位置,因而稱為倒排索引(inverted index)灼舍。帶有倒排索引的文件我們稱為倒排索引文件吼和,簡稱倒排文件(inverted file)。
- 文檔
存儲在ES上的主要實(shí)體叫文檔
- 文檔類型(廢棄)
在ES中骑素,一個索引對象可以存儲很多不同用途的對象炫乓。
- 映射
存儲有關(guān)字段的信息,每一個文檔類型都有自己的映射献丑。
- 面向文檔
在應(yīng)用程序中對象很少只是一個簡單的鍵和值的列表末捣。通常,它們擁有更復(fù)雜的數(shù)據(jù)結(jié)構(gòu)创橄,可能包括日期箩做、地理信息、其他對象或者數(shù)組等妥畏。
也許有一天你想把這些對象存儲在數(shù)據(jù)庫中邦邦。使用關(guān)系型數(shù)據(jù)庫的行和列存儲,這相當(dāng)于是把一個表現(xiàn)力豐富的對象擠壓到一個非常大的電子表格中:你必須將這個對象扁平化來適應(yīng)表結(jié)構(gòu)--通常一個字段>對應(yīng)一列--而且又不得不在每次查詢時重新構(gòu)造對象咖熟。
Elasticsearch 是 面向文檔 的,意味著它存儲整個對象或 文檔_柳畔。Elasticsearch 不僅存儲文檔馍管,而且 _索引 每個文檔的內(nèi)容使之可以被檢索。在 Elasticsearch 中薪韩,你 對文檔進(jìn)行索引确沸、檢索捌锭、排序和過濾--而不是對行列數(shù)據(jù)。這是一種完全不同的思考數(shù)據(jù)的方式罗捎,也是 Elasticsearch 能支持復(fù)雜全文檢索的原因观谦。
三. ES交互語法
3.1 基本結(jié)構(gòu)
curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'
< > | 描述 |
---|---|
VERB | 適當(dāng)?shù)?HTTP 方法 或 謂詞 : GET、 POST桨菜、 PUT豁状、 HEAD 或者 DELETE |
PROTOCOL | http 或者 https(如果你在 Elasticsearch 前面有一個 https 代理) |
HOST | Elasticsearch 集群中任意節(jié)點(diǎn)的主機(jī)名,或者用 localhost 代表本地機(jī)器上的節(jié)點(diǎn) |
PORT | 運(yùn)行 Elasticsearch HTTP 服務(wù)的端口號倒得,默認(rèn)是 9200 |
PATH | API 的終端路徑(例如 _count 將返回集群中文檔數(shù)量)泻红。Path 可能包含多個組件,例如:_cluster/stats 和 _nodes/stats/jvm |
QUERY_STRING | 任意可選的查詢字符串參數(shù) (例如 ?pretty 將格式化地輸出 JSON 返回值霞掺,使其更容易閱讀) |
BODY | 一個 JSON 格式的請求體 (如果請求需要的話) |
舉例:
curl -XGET 'http://localhost:9200/_count?pretty' -d '
{
"query": {
"match_all": {}
}
}
'
3.2 常用命令
-
檢測集群是否健康
curl 'localhost:9200/_cat/health?v'
-
查看分片狀態(tài)
curl -X GET 'http://localhost:9200/_cluster/health?pretty'
-
獲取集群節(jié)點(diǎn)
curl 'localhost:9200/_cat/nodes?v'
-
列出所有索引
curl 'localhost:9200/_cat/indices?v'
-
查詢索引數(shù)據(jù)
curl 'localhost:9200/brand/_search?pretty=true'
-
創(chuàng)建索引
curl -XPUT 'localhost:9200/customer?pretty'
-
刪除索引
curl -XDELETE 'http://localhost:9200/customer'
-
插件安裝
./plugin install mobz/elasticsearch-head
中文分詞插件
./plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v1.10.6/elasticsearch-analysis-ik-1.10.6.zip
-
后臺啟動安裝
./elasticsearch -d
-
分析器-分析語句
curl -XGET 'localhost:9200/_analyze?pretty' -H 'Content-Type: application/json' -d' { "analyzer": "standard", "text": "Text to analyze" } '
3.3. 查詢命令
-
query_string語法
curl -XGET 'localhost:9200/product/spu/_search?pretty=true' -d '{ "query" : { "query_string" : {"query" : "brandName:本田"} } }'
-
分頁查詢
curl -XGET 'localhost:9200/product/spu/_search?pretty=true' -d '{ "from" : 1, "size" : 1, "query" : { "query_string" : {"query" : "brandName:本田"} } }'
-
增加version值
curl -XGET 'localhost:9200/product/spu/_search?pretty=true' -d '{ "version" : true, "from" : 1, "size" : 1, "query" : { "query_string" : {"query" : "brandName:本田"} } }'
-
限制得分
curl -XGET 'localhost:9200/product/spu/_search?pretty=true' -d '{ "version" : true, "min_score" : 2.4, "query" : { "query_string" : {"query" : "brandName:本田"} } }'
-
選擇要返回的字段
curl -XGET 'localhost:9200/product/spu/_search?pretty=true' -d '{ "fields" : ["brandName","spuName"], "version" : true, "min_score" : 2.4, "query" : { "query_string" : {"query" : "brandName:本田"} } }'
-
部分字段(驗(yàn)證失敗谊路,可能是版本相關(guān))
curl -XGET 'localhost:9200/product/spu/_search?pretty=true' -d '{ "partial_fields" : { "partial1" : { "include" : ["brand*"], "exclude" : ["spu*"] } }, "query" : { "query_string" : {"query" : "brandName:本田"} } }'
-
腳本字段(驗(yàn)證失敗)
curl -XGET 'localhost:9200/product/spu/_search?pretty=true' -d '{ "script_fields" : { "newPrice" : { "script" : "_source.guidePrice - reducePrice", "param" : { "reducePrice" : 10000 } } }, "query" : { "query_string" : {"query" : "brandName:本田"} } }'
-
用constant_score轉(zhuǎn)換query為filter
curl -XGET 'localhost:9200/product/spu/_search?pretty' -H 'Content-Type: application/json' -d' { "query" : { "constant_score" : { "filter" : { "term" : { "spuName" : "手" } } } } } '
-
組合filter
curl -XGET 'localhost:9200/my_store/products/_search?pretty' -H 'Content-Type: application/json' -d' { "query" : { "filtered" : { "filter" : { "bool" : { "should" : [ { "term" : {"price" : 20}}, { "term" : {"productID" : "XHDK-A-1293-#fJ3"}} ], "must_not" : { "term" : {"price" : 30} } } } } } } '
3.4. 分析命令
-
基本語法
curl -XGET 'localhost:9200/product/_analyze?pretty' -H 'Content-Type: application/json' -d' { "field": "spuName", "text": "手動" } '
3.5. 查詢驗(yàn)證命令
-
基本語法
curl -XGET 'localhost:9200/my_index/my_type/_validate/query?explain&pretty' -H 'Content-Type: application/json' -d' { "query": { "bool": { "should": [ { "match": { "title": "Foxes"}}, { "match": { "english_title": "Foxes"}} ] } } } '
3.6. 批量操作
- 基本語法
bulk API 允許在單個步驟中進(jìn)行多次 create 、 index 菩彬、 update 或 delete 請求缠劝。 如果你需要索引一個數(shù)據(jù)流比如日志事件,它可以排隊(duì)和索引數(shù)百或數(shù)千批次骗灶。
bulk 與其他的請求體格式稍有不同惨恭,如下所示:
{ action: { metadata }}\n
{ request body }\n
{ action: { metadata }}\n
{ request body }\n
action/metadata 行指定 哪一個文檔 做 什么操作 。
action 必須是以下選項(xiàng)之一:
- create
如果文檔不存在矿卑,那么就創(chuàng)建它喉恋。 - index
創(chuàng)建一個新文檔或者替換一個現(xiàn)有的文檔。 - update
部分更新一個文檔母廷。 - delete
刪除一個文檔轻黑。
- 案例
curl -XPOST 'localhost:9200/_bulk?pretty' -H 'Content-Type: application/json' -d'
{ "delete": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "create": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "title": "My first blog post" }
{ "index": { "_index": "website", "_type": "blog" }}
{ "title": "My second blog post" }
{ "update": { "_index": "website", "_type": "blog", "_id": "123", "_retry_on_conflict" : 3} }
{ "doc" : {"title" : "My updated blog post"} }
'
四. SpringBoot與Elasticsearch集成
-
pom文件中添加添加依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> <!-- 解決es no jna warning--> <dependency> <groupId>com.sun.jna</groupId> <artifactId>jna</artifactId> <version>3.0.9</version> </dependency>
-
application.yml添加配置
spring: data: elasticsearch: cluster-nodes: 127.0.0.1:9300
注意:elasticsearch jar版本要與安裝的服務(wù)版本相容
五. Elasticsearch集群健康狀態(tài)
5.1 狀態(tài)說明
- green 最健康得狀態(tài),說明所有的分片包括備份都可用
- yellow 基本的分片可用琴昆,但是備份不可用(或者是沒有備份)
- red 部分的分片可用氓鄙,表明分片有一部分損壞。此時執(zhí)行查詢部分?jǐn)?shù)據(jù)仍然可以查到业舍,遇到這種情況抖拦,還是趕快解決比較好
5.2 狀態(tài)為yellow的解決方法
分片與副本分片
分片用于Elasticsearch在你的集群中分配數(shù)據(jù)。想象把分片當(dāng)作數(shù)據(jù)的容器舷暮。文檔存儲在分片中态罪,然后分片分配給你集群中的節(jié)點(diǎn)上。
當(dāng)你的集群擴(kuò)容或縮小下面,Elasticsearch將會自動在你的節(jié)點(diǎn)間遷移分片复颈,以使集群保持平衡。
一個分片(shard)是一個最小級別的“工作單元(worker unit)”,它只是保存索引中所有數(shù)據(jù)的一小片.我們的文檔存儲和被索引在分片中沥割,但是我們的程序不知道如何直接與它們通信耗啦。取而代之的是凿菩,他們直接與索引通信.Elasticsearch中的分片分為主分片和副本分片,復(fù)制分片只是主分片的一個副本,它用于提供數(shù)據(jù)的冗余副本帜讲,在硬件故障之后提供數(shù)據(jù)保護(hù)衅谷,同時服務(wù)于像搜索和檢索等只讀請求,主分片的數(shù)量和復(fù)制分片的數(shù)量都可以通過配置文件配置似将。但是主切片的數(shù)量只能在創(chuàng)建索引時定義且不能修改.相同的分片不會放在同一個節(jié)點(diǎn)上获黔。
分片算法
shard = hash(routing) % number_of_primary_shards
routing值是一個任意字符串,它默認(rèn)是_id但也可以自定義玩郊,這個routing字符串通過哈希函數(shù)生成一個數(shù)字肢执,然后除以主切片的數(shù)量得到一個余數(shù)(remainder),余數(shù)的范圍永遠(yuǎn)是0到number_of_primary_shards - 1译红,這個數(shù)字就是特定文檔所在的分片预茄。
這也解釋了為什么主切片的數(shù)量只能在創(chuàng)建索引時定義且不能修改:如果主切片的數(shù)量在未來改變了,所有先前的路由值就失效了侦厚,文檔也就永遠(yuǎn)找不到了耻陕。
所有的文檔API(get、index刨沦、delete诗宣、bulk、update想诅、mget)都接收一個routing參數(shù)召庞,它用來自定義文檔到分片的映射。自定義路由值可以確保所有相關(guān)文檔.比如用戶的文章,按照用戶賬號路由,就可以實(shí)現(xiàn)屬于同一用戶的文檔被保存在同一分片上来破。
單機(jī)(空集群)狀態(tài)為yellow原因
由于我們是單節(jié)點(diǎn)部署elasticsearch篮灼,而默認(rèn)的分片副本數(shù)目配置為1,而相同的分片不能在一個節(jié)點(diǎn)上徘禁,所以就存在副本分片指定不明確的問題诅诱,所以顯示為yellow,我們可以通過在elasticsearch集群上添加一個節(jié)點(diǎn)來解決問題送朱,如果你不想這么做娘荡,你可以刪除那些指定不明確的副本分片(當(dāng)然這不是一個好辦法)但是作為測試和解決辦法還是可以嘗試的,下面我們試一下刪除副本分片的辦法
解決方案
curl -XPUT "http://localhost:9200/_settings" -d' { "number_of_replicas" : 0 } '
六. 其他
6.1 版本沖突/事務(wù)
Elasticsearch使用_version來確保所有的改變操作都被正確排序驶沼。如果一個舊的版本出現(xiàn)在新版本之后炮沐,它就會被忽略掉。
我們可以利用_version的優(yōu)點(diǎn)來確保我們程序修改的數(shù)據(jù)沖突不會造成數(shù)據(jù)丟失回怜。我們可以按照我們的想法來指定_version的數(shù)字大年。如果數(shù)字錯誤,請求就是失敗。
實(shí)例演示:
- 插入數(shù)據(jù)
curl -XPOST 'localhost:9200/employee/it/1?pretty' -H 'Content-Type: application/json' -d'
{
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
'
- 修改數(shù)據(jù)
curl -XPUT 'localhost:9200/employee/it/1?pretty' -H 'Content-Type: application/json' -d'
{
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
'
- 再次修改數(shù)據(jù)
curl -XPUT 'localhost:9200/employee/it/1?version=1&pretty' -H 'Content-Type: application/json' -d'
{
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
'
異常如下:
{
"error" : {
"root_cause" : [ {
"type" : "version_conflict_engine_exception",
"reason" : "[it][1]: version conflict, current [2], provided [1]",
"shard" : "3",
"index" : "employee"
} ],
"type" : "version_conflict_engine_exception",
"reason" : "[it][1]: version conflict, current [2], provided [1]",
"shard" : "3",
"index" : "employee"
},
"status" : 409
}