es的api除了提供了基本的curd操作外,還有兩個針對批量的操作分别是:
1,批量的讀取操作(mget)
2,批量的寫入操作(bulk)
本篇文章先介紹mget的用法
Multi Get api 簡稱(mget)它允許我們一次get大量的document,與get單條資料的api get方法類似,mget查詢是基于index,type(可選),id三個條件進行的,比如我們可以一次mget 50條資料,這50條資料可以是在50個不同index中,并且每一個get都可以單獨指定它的路由查詢資訊,或者傳回的字段内容。
mget可以批量的根據index,type,id三個字段來擷取一批資料,它不能用來查詢,最少得需要知道index 和 id兩個字段的值,才能進行get,這一點與query是不一樣的。
用法如下:
mget可以有三種請求頭
(1)不指定index
GET /_mget
{
"docs" : [
{
"_index" : "test",
"_type" : "_doc",
"_id" : "1"
},
{
"_index" : "test",
"_type" : "_doc",
"_id" : "2"
}
]
}
複制
(2)指定index
GET /test/_mget
{
"docs" : [
{
"_type" : "_doc",
"_id" : "1"
},
{
"_type" : "_doc",
"_id" : "2"
}
]
}
複制
(3)指定index和type
GET /test/type/_mget
{
"docs" : [
{
"_id" : "1"
},
{
"_id" : "2"
}
]
}
簡寫方式
GET /test/type/_mget
{
"ids" : ["1", "2"]
}
複制
此外,還可以單獨的設定對傳回的資料(source)進行過濾操作,預設情況下如果這條資料被store了,那麼它會傳回整個document。
幾種過濾的方式:
使用source過濾
GET /_mget
{
"docs" : [
{
"_index" : "test",
"_type" : "_doc",
"_id" : "1",
"_source" : false
},
{
"_index" : "test",
"_type" : "_doc",
"_id" : "2",
"_source" : ["field3", "field4"]
},
{
"_index" : "test",
"_type" : "_doc",
"_id" : "3",
"_source" : {
"include": ["user"],
"exclude": ["user.location"]
}
}
]
}
複制
使用fields過濾:
GET /_mget
{
"docs" : [
{
"_index" : "test",
"_type" : "_doc",
"_id" : "1",
"stored_fields" : ["field1", "field2"]
},
{
"_index" : "test",
"_type" : "_doc",
"_id" : "2",
"stored_fields" : ["field3", "field4"]
}
]
}
複制
source和fields的主要差別在于,source預設将整個json存在一起,在讀取時候隻需要加載一次然後再解析出來需要的字段,而store字段則是每個字段單獨的存儲,是以大部分時候推薦使用source字段,雖然會多占一些存儲空間,但在讀取字段數比較多的情況下,source的性能是比store字段要更好的,但是如果你disable了source字段,則意味着:
(1)你不能夠高亮文本(不推薦在服務端做高亮,推薦用戶端做)
(2)你不能reindex索引
(3)你不能做partial update
是以綜合考慮,推薦還是使用source字段
在get的時候,還可以使用路由字段,如下:
GET /_mget?routing=key1
{
"docs" : [
{
"_index" : "test",
"_type" : "_doc",
"_id" : "1",
"routing" : "key2"
},
{
"_index" : "test",
"_type" : "_doc",
"_id" : "2"
}
]
}
複制
最後在看下在java api裡面如何使用:
//建構一個mget的查詢
MultiGetRequestBuilder multi_get= client.prepareMultiGet();
//添加兩條get資料
multi_get.add("a_active","active","1");
multi_get.add("b_active","active","2","3");
//擷取響應
MultiGetResponse mgr= multi_get.get();
//循環讀取
for (MultiGetItemResponse itemResponse : mgr) {
GetResponse response = itemResponse.getResponse();
//如果存在則列印響應消息
if (response.isExists()) {
String json = response.getSourceAsString();
System.out.println(" source data: "+json);
}
}
複制
總結:
本文介紹了es裡面的批量讀取資料的方法mget,這個方法在日常開發中的使用頻度并不是很高,但是在特定場景下會擁有較高的效率,比如上篇文章介紹的es的分布式查詢的原理的時候,在第一階段query從每個shard上查詢本地的page資料,然後傳回到coordinating節點上,并重新進行全局排序再取指定分頁的n條資料,接着到了第二階段fetch,要把這批資料的内容讀取出來傳回給client,這個時候就是mget發力的時候,通過id組裝成一個mget請求,然後發送到每個shard裡面擷取結果資料,最終組裝後在傳回給client,這樣一來比單條get的效率要高很多,另外對索引的寫入也是如此,下篇文章我們會介紹批量寫入bulk的用法。