天天看點

elasticsearch裡面的關于批量讀取mget的用法

elasticsearch裡面的關于批量讀取mget的用法

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的用法。