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代替更新操作,重新索引文檔。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM