開始第一步
讓我們建立一個員工目錄
我們首先要做的是存儲員工數(shù)據(jù)膝藕,每個文檔(document)(行)代表一個員工。所以為了創(chuàng)建員工目錄,我們將進行如下操作:
- 為每個員工的文檔(document)建立索引,每個文檔包含了相應(yīng)員工的所有信息莫辨。
- 每個文檔的類型為employee
- employee類型歸屬于索引megacorp
- megacorp索引存儲在ElasticSearch集群中。
實際上這些都是很容易的,我們通過一個命令執(zhí)行完成操作沮榜。
curl -XPUT "localhost:9200/megacorp/employee/1?pretty" -d '{
"first_name":"John",
"last_name":"Smith",
"age":25,
"about":"I love to go rock climbing",
"interests":["sports","music"]
}'
注:在Windows下命令如下:
curl -H "application/json" -XPUT "localhost:9200/megacorp/employee/1?pretty" -d "{
\ "first_name\":\"John\",
\"last_name\":\"Smith\",
\ "age\":25,
\"about\":\"I love to go rock climbing\",
\ "interests\":[\"sports\",\"music\"]
}"
自增ID
curl -XPOST "localhost:9200/website/blog/" -d '{
"title" : "My first blog entry",
"text" : "Just trying this out...",
"date" : "2014/01/01"
}'
響應(yīng)如下:
{
"_index" : "website",
"_type" : "blog",
"_id" : "X7cGE2UB2XL2Aw5Pme58",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 2,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}
檢索文檔
curl -XGET "localhost:9200/website/blog/123?pretty"
響應(yīng)如下:
{
"_index" : "website",
"_type" : "blog",
"_id" : "123",
"_version" : 1,
"found" : true,
"_source" : {
"title" : "My first blog entry",
"text" : "Just trying this out...",
"date" : "2014/01/01"
}
}
檢索文檔的一部分
通常盘榨,GET請求將返回文檔的全部,存儲在_source參數(shù)中蟆融。但是你可能感興趣的字段只是title草巡。請求個別字段可以使用_source參數(shù)。多個字段可以使用逗號分隔:
curl -i -XGET "localhost:9200/website/blog/123?_source=title,text&pretty"
_source字段現(xiàn)在只包含我們請求的字段,而且過濾了date字段:
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-length: 197
{
"_index" : "website",
"_type" : "blog",
"_id" : "123",
"_version" : 1,
"found" : true,
"_source" : {
"text" : "Just trying this out...",
"title" : "My first blog entry"
}
}
或者你只想得到_source字段而不要其他的元數(shù)據(jù),你可以這樣請求:
curl -i -XGET "localhost:9200/website/blog/123/_source?pretty"
它僅僅返回:
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-length: 101
{
"title" : "My first blog entry",
"text" : "Just trying this out...",
"date" : "2014/01/01"
}
檢查文檔是否存在
如果你想做的只是檢查文檔是否存在——-你對內(nèi)容完全不感興趣型酥,那就使用HEAD方法代替GET,HEAD請求不會返回響應(yīng)體山憨。只有HTTP頭:
curl -i -XHEAD "localhost:9200/website/blog/123?pretty"
ElasticSearch將會返回 200OK 狀態(tài)(如果你的文檔存在):
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-length: 224
如果不存在返回 404 Not Found:
HTTP/1.1 404 Not Found
content-type: application/json; charset=UTF-8
content-length: 83
當然,這只代表你在查詢的那一刻文檔不存在弥喉,但并不帶表幾毫秒后依舊不存在郁竟。另一進程在這期間可能創(chuàng)建新文檔。
更新整個文檔
文檔在ElasticSearch中是不可變的——–我們不能修改他們由境。
curl -i -XPUT "localhost:9200/website/blog/123" -d '{
"title":"My first blog entry",
"text":"I am starting to get the hang of this...",
"date":"2014/01/02"
}'
在響應(yīng)中棚亩,我們可以看到ElasticSearch把_version增加了。
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-length: 223
{
"_index" : "website",
"_type" : "blog",
"_id" : "123",
"_version" : 2,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 2,
"failed" : 0
},
"_seq_no" : 1,
"_primary_term" : 1
}
在內(nèi)部虏杰,ElasticSearch已經(jīng)標記舊文檔為刪除并添加了一個完整的新文檔讥蟆。舊版本文檔不會立即消失,但你也不能去訪問它纺阔。ElasticSearch會在你繼續(xù)索引更多數(shù)據(jù)時清理被刪除的文檔瘸彤。
創(chuàng)建一個新文檔
當索引一個文檔,我們?nèi)绾未_定是完全創(chuàng)建了一個新的還是覆蓋了一個已經(jīng)存在的呢笛钝?
請記住_index,_type,_id三者唯一確定一個文檔质况。所以要想保證文檔是新加入的,最簡單的方式是使用POST方法讓ElasticSearch自動生成唯一_id
curl -i -XPOST "localhost:9200/website/blog/" -d '{
....
}'
然而婆翔,如果想使用自定義的_id,我們必須告訴ElasticSearch應(yīng)該在_index,_type,_id三者不同時才接受請求拯杠。為了做到這點有兩種方法,他們其實做的是同一件事啃奴。你可以選擇適合自己的方式:
第一種方法使用 op_type 查詢參數(shù):
curl -XPUT "localhost:9200/website/blog/123?op_type=create" -d '{
........
}'
第二種方法是在URL后加 /_create 作為端點
curl -XPUT "localhost:9200/website/blog/123/_create" -d '{
........
}'
如果請求成功的創(chuàng)建了一個新文檔,ElasticSearch將返回正常的元數(shù)據(jù)且響應(yīng)狀態(tài)嗎是201 Created雄妥。
另一方面最蕾,如果包含相同的 _index,_type,_id的文檔已經(jīng)存在,ElasticSearch將返回409 Conflict響應(yīng)狀態(tài)碼老厌,錯誤信息如下
{
"error" : {
"root_cause" : [
{
"type" : "version_conflict_engine_exception",
"reason" : "[blog][123]: version conflict, document already exists (current version [2])",
"index_uuid" : "U3-JJt16SKmUn6rBuBDOfw",
"shard" : "0",
"index" : "website"
}
],
"type" : "version_conflict_engine_exception",
"reason" : "[blog][123]: version conflict, document already exists (current version [2])",
"index_uuid" : "U3-JJt16SKmUn6rBuBDOfw",
"shard" : "0",
"index" : "website"
},
"status" : 409
}
刪除文檔
刪除文檔的語法模式與之前基本一致瘟则,只不過要使用 DELETE 方法:
curl -XDELETE "localhost:9200/website/blog/123"
如果文檔被找到,ElasticSearch將返回 200OK 狀態(tài)碼枝秤, _version 數(shù)字增加醋拧;如果文檔未找到,我們將得到一個404 Not Found 狀態(tài)碼,盡管文檔不存在丹壕,_version 依舊增加了庆械,這是內(nèi)部記錄的一部分,它確保在多節(jié)點間不同操作可以有正確的順序菌赖。
文檔局部更新
最簡單的 update 請求表單接受一個局部文檔參數(shù)doc缭乘,它會合并到現(xiàn)有文檔中------對象合并在一起,存在的標量字段被覆蓋琉用,新字段被添加堕绩。
curl -XPOST "localhost:9200/website/blog/1/_update" -d '{
"doc":{
"tags":["testing"],
"views":0
}
}'
如果請求成功,我們將看到類似請求的響應(yīng)結(jié)果:
{
"_index":"website",
"_id":"1",
"_type":"blog",
"_version":3
}
檢索文檔顯示被更新的_source字段:
{
"_index":"website",
"_id":"1",
"_type":"blog",
"_version":3
"found":true,
"_source":{
"title":"My first blog entry",
"text":"Starting to get the hang of this...",
"tags":["testing"],
"views":0
}
}
我們新添加的字段已經(jīng)被添加到_source字段中邑时。
檢索多個文檔
ElasticSearch檢索多個文檔依舊非撑簦快。合并多個請求可以避免每個請求單獨的網(wǎng)絡(luò)開銷晶丘。如果你需要從ElasticSearch中檢索多個文檔黍氮,相對于一個一個的檢索,更快的方式是在一個請求中使用multi-get或者mget API铣口。
mget API參數(shù)是一個 docs 數(shù)組滤钱,數(shù)組的每個節(jié)點定義一個文檔的 _index,_type,_id 元數(shù)據(jù)。如果你只想檢索一個或幾個確定的字段脑题,也可以定義一個 _source 參數(shù):
curl -i -XGET "localhost:9200/_mget" -d '{
"docs":[
{
"_index":"megacorp",
"_type":"employee",
"_id":2
},{
"_index":"megacorp",
"_type":"employee",
"_id":3,
"_source":"age"
}
]
}'
響應(yīng)體如下:
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-length: 545
{
"docs" : [
{
"_index" : "megacorp",
"_type" : "employee",
"_id" : "2",
"_version" : 2,
"found" : true,
"_source" : {
"first_name" : "Douglas",
"last_name" : "Fir",
"age" : 35,
"about" : "I like to build cabinets",
"interests" : [
"forestry"
]
}
},
{
"_index" : "megacorp",
"_type" : "employee",
"_id" : "3",
"_version" : 1,
"found" : true,
"_source" : {
"age" : 32
}
}
]
}
如果你想檢索的文檔在同一個 _index 中(甚至在同一個 _type 中)件缸,你就可以在URL中定義一個默認的 _index 或者 /_index/_type。
你依舊可以在單獨的請求中使用這些值:
curl -i -XGET "192.168.6.101:9200/megacorp/employee/_mget" -d '{
"docs":[
{"_id":2},
{"_index":"website","_type":"blog","_id":123}
]
}'
結(jié)果如下:
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-length: 655
{
"docs" : [
{
"_index" : "megacorp",
"_type" : "employee",
"_id" : "2",
"_version" : 2,
"found" : true,
"_source" : {
"first_name" : "Douglas",
"last_name" : "Fir",
"age" : 35,
"about" : "I like to build cabinets",
"interests" : [
"forestry"
]
}
},
{
"_index" : "website",
"_type" : "blog",
"_id" : "123",
"_version" : 2,
"found" : true,
"_source" : {
"title" : "My first blog entry",
"text" : "I am starting to get the hang of this...",
"date" : "2014/01/02"
}
}
]
}
事實上叔遂,如果所有文檔具有相同的 _index 和 _type他炊,你可以通過簡單的 ids 數(shù)組來代替完整的 docs 數(shù)組:
curl -i -XGET "192.168.6.101:9200/megacorp/employee/_mget" -d '{
"ids":["2","3"]
}'
更省時的批量操作
就像 mget 允許我們一次性檢索多個文檔一樣,bulk API允許我們使用單一請求來實現(xiàn)多個文檔的create已艰,index痊末,delete,update操作哩掺≡涞可以以成百上千的數(shù)據(jù)為一個批次按序進行操作。
bulk 的請求體如下所示嚼吞,它有一點不同尋常盒件。
{action : {metadata}}\n
{request body}\n
{action:{metadata}}\n
{request body}\n
.........
這種格式類似于用"\n"符號連接起來的一行一行的JSON文檔流,兩個重要的點需要注意:
- 每行必須以"\n"結(jié)尾舱禽,包括最后一行炒刁。
- 每行不能包含未被轉(zhuǎn)義的換行符,這意味著JSON不能被美化打印
action/metadata定義了文檔行為發(fā)生在了哪個文檔之上誊稚。
行為(action)必須是以下幾種:
行為 | 解釋 |
---|---|
create | 當文檔不存在時創(chuàng)建 |
index | 創(chuàng)建新文檔或替換已有文檔 |
update | 局部更新文檔 |
delete | 刪除一個文檔 |
在索引翔始,更新罗心,刪除,創(chuàng)建一個文檔時必須指定文檔的_index,_type,_id這些元數(shù)據(jù)城瞎。
例如刪除請求看起來像這樣:
{"delete":{"_index":"megacorp","_type","employee","_id","2"}}
請求體(request body)由文檔的 _source組成-------文檔包含的一些字段以及其值渤闷。它被index和create操作所必須,這是有道理的:你必須提供文檔用來索引全谤。
{"create":{"_index":"website","_type":"blog","_id":"123"}}
{"title":"My first blog post"}
如果不定義_id肤晓,ID將會被自動創(chuàng)建:
{"index":{"_index":"website","_type":"blog"}}
{"title":"My second blog post"}
為了將這些放在一起,bulk 請求表單是這樣的:
curl -i -XPOST "localhost:9200/_bulk" -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 update blog post"}}
'
你可以在同一個 index 下的同一個 type 里批量索引日志數(shù)據(jù)认然。為每個文檔指定相同的元數(shù)據(jù)是多余的补憾。就像 mget API,bulk 請求也可以在URL中使用 /_index 或 /_index/_type:
curl -i -XPOST "localhost:9200/website/_bulk" -d '
{"index":{"_type":"log"}}
{"event":"User logged in"}
'
你依舊可以覆蓋元數(shù)據(jù)行的 _index和 _type卷员,在沒有覆蓋時它會使用URL中的值作為默認值:
curl -i -XPOST "localhost:9200/website/log/_bulk" -d '
{"index":{}}
{"event":"User logged in"}
{"index":{"_type":"blog"}}
{"title":"Overriding the default type"}
'