1. 程式人生 > >Elasticsearch增刪改查 之 —— Update更新

Elasticsearch增刪改查 之 —— Update更新

更新操作,一般用這個的,應該不會很多吧!ES本身還是一個傾向於查詢檢索的框架,對於這種更新的操作,太過頻繁總歸是不好的。
不過閱讀本篇後,你可以使用Script對所有的文件執行更新操作,也可以使用doc對部分文件執行更新,也可以使用upsert對不存在的文件執行新增操作。

更新

Update更新操作允許ES獲得某個指定的文件,可以通過指令碼等操作對該文件進行更新。可以把它看成是先刪除再索引的原子操作,只是省略了返回的過程,這樣即節省了來回傳輸的網路流量,也避免了中間時間造成的文件修改衝突。
下面就是更新的例子:

curl -XPUT localhost:9200/test/type1/1 -d '{
    "counter" : 1,
    "tags" : ["red"]
}'

指令碼更新

Es支援通過指令碼更改文件的資訊:

curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
    "script" : {
        "inline": "ctx._source.counter += count",
        "params" : {
            "count" : 4
        }
    }
}'

上面就是通過引數來為每個counter加4.
也可以新增某個標記:

curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
    "script" : {
        "inline": "ctx._source.tags += tag",
        "params" : {
            "tag" : "blue"
        }
    }
}'

除了_source欄位,可以通過ctx來獲得_index_type_id_version_parent_timestamp_ttl等欄位資訊。

也可以新增某個欄位:

curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
    "script" : "ctx._source.name_of_new_field = \"value_of_new_field\""
}'

移除欄位:

curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
    "script" : "ctx._source.remove(\"name_of_field\")"
}'

也支援稍微複雜點的邏輯,比如根據某個標記執行不同的操作。比如如果有blue這個標記,則刪除該文件;否則什麼也不做:

curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
    "script" : {
        "inline": "ctx._source.tags.contains(tag) ? ctx.op = \"delete\" : ctx.op = \"none\"",
        "params" : {
            "tag" : "blue"
        }
    }
}'

只更新部分文件

上面的指令碼是對所有的文件都起作用,這裡講解下如何只對部分文件進行修改。使用doc可以實現簡單的遞迴合併、內部合併、替換KV以及陣列。

curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
    "doc" : {
        "name" : "new_name"
    }
}'

如果同時使用了doc和script,那麼doc的操作會自動忽略。因此最好是把特殊的操作也放在指令碼中。

更新檢測

如果使用doc,那麼會自動合併到現有的文件中。如果doc中定義的部分與現在的文件相同,則預設不會執行任何動作。設定detect_noop=false,就會無視是否修改,強制合併到現有的文件。

curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
    "doc" : {
        "name" : "new_name"
    },
    "detect_noop": false
}'

上面的例子中,如果name欄位為new_name,無論當前的文件是否與doc中定義的相同,都會把doc合併到文件中。

upsert插入

這個引數主要用於當文件不存在時,ES的操作。

curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
    "script" : {
        "inline": "ctx._source.counter += count",
        "params" : {
            "count" : 4
        }
    },
    "upsert" : {
        "counter" : 1
    }
}'

在上面的例子中,當文件存在時,執行指令碼;當文件不存在時,upsert中的內容就會插入到對應的文件中。

如果你想無論文件是否存在都執行指令碼操作,那麼可以使用引數scripted_upsert為true。

curl -XPOST 'localhost:9200/sessions/session/dh3sgudg8gsrgl/_update' -d '{
    "scripted_upsert":true,
    "script" : {
        "id": "my_web_session_summariser",
        "params" : {
            "pageViewEvent" : {
                "url":"foo.com/bar",
                "response":404,
                "time":"2014-01-01 12:32"
            }
        }
    },
    "upsert" : {}
}'

相對於之前的使用Upsert中的內容新增到不存在的文件,使用doc_as_upsert可以在文件不存在的時候,把doc中的內容插入到文件中。

curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
    "doc" : {
        "name" : "new_name"
    },
    "doc_as_upsert" : true
}'

引數

retry_on_conflict

當執行索引和更新的時候,有可能另一個程序正在執行更新。這個時候就會造成衝突,這個引數就是用於定義當遇到衝突時,再過多長時間執行操作。

routing

Routing is used to route the update request to the right shard and sets the routing for the upsert request if the document being updated doesn’t exist. Can’t be used to update the routing of an existing document.

parent

Parent is used to route the update request to the right shard and sets the parent for the upsert request if the document being updated doesn’t exist. Can’t be used to update the parent of an existing document.

timeout

當分片不可用的時候,等待多長時間

consistency

The write consistency of the index/delete operation.
索引/刪除操作的寫一致性!不知道怎麼用

refresh

當執行操作的時候,會自動重新整理索引。

fields

執行完更新後,返回的欄位

version & version_type

更新操作會使用版本號來確定 拿到文件到執行更新期間,文件是否被修改過。也可以通過特定的版本號,更新文件。如果使用force作為版本號,那麼更新操作將不會再改變版本號。注意,這樣就無法保證文件是否被修改了。

外部版本號

更新操作是不支援外部版本號的,因為本來外部版本號就脫離系統的版本控制,如果再執行更新操作,那就徹底亂了。如果使用了外部版本號,可以使用Index代替更新操作,重新索引文件。