簡介
ElasticSearch的文檔寫入是以不可修改的形式寫入的,一條文檔記錄一旦被寫入其本身就不能被修改了。然而祭阀,現(xiàn)實中存在修改這些數(shù)據(jù)的需求,那怎么辦呢鲜戒?當上帝給你關(guān)上一扇門的時候专控,他一定給你留了一個窗口。雖然我們不能直接修改這個文檔本身遏餐,但是我們可以通過更新一條_id
一樣的文檔伦腐,并更新版本號的方式來修改這條記錄。我們可以通過三種姿勢進行更新失都。
姿勢1柏蘑,直接index
PUT test1/_doc/1
{
"name": "bbbb"
}
# Do query
PUT test1/_doc/1
{
"name": "bbbb",
"age": 33
}
# Do query
PUT test1/_doc/1
{
"name": "bbbb"
}
# Do query
按順序執(zhí)行上面的三條put操作幸冻,然后查詢,我們可以看到相應(yīng)的查詢結(jié)果是:
"_version": 1
"_source" : {
"name" : "bbbb"
}
=========================
"_version": 2
"_source" : {
"name" : "bbbb",
"age" : 33
}
=========================
"_version": 3
"_source" : {
"name" : "bbbb"
}
可以看到每次put之后咳焚,版本號都會遞增1位洽损,同時后面的數(shù)據(jù)會覆蓋之前的數(shù)據(jù)。
如果我并不想每次都通過這樣把全部文檔內(nèi)容再輸入一次的形式來革半,而是希望基于前一個版本的文檔進行增減或者修改碑定,那又應(yīng)該怎么做呢。ES為我們提供了update API又官。
姿勢2延刘,使用update API
ES 提供了update API,使我們可以針對某個id的文檔赏胚,進行局部更新访娶。我們可以使用painless腳本或者直接在update中設(shè)置doc字段的參數(shù)的形式進行。
考慮以下文檔觉阅。
PUT test14/_doc/1
{
"name": "aaaa",
"age": 15,
"sex": "male"
}
如果我想修改年齡的話崖疤,可以有兩種方法來進行:
POST test14/_update/1
{
"doc": {
"age": 14
}
}
POST test14/_update/1
{
"script": {
"lang": "painless",
"source": """
ctx._source.age = 14
"""
}
}
兩種方法都可以將age修改為14。
如果我們想增加一個屬性”weight“該怎么做呢典勇?
POST test14/_update/1
{
"doc": {
"weight": 90
}
}
POST test14/_update/1
{
"script": {
"lang": "painless",
"source": """
ctx._source.weight = 90
"""
}
}
如果我們想移除”sex“字段劫哼,這種情況下,只能用painless腳本了割笙。
POST test14/_update/1
{
"script": {
"lang": "painless",
"source": """
ctx._source.remove("sex");
"""
}
}
這三種情況是最基本的权烧,還有一些其他用法,可以參考update的官方文檔伤溉。
https://www.elastic.co/guide/en/elasticsearch/reference/7.2/docs-update.html
需要注意般码,使用update api只能使用ES索引的內(nèi)置版本號,如果強行指定版本號乱顾,update操作會發(fā)生錯誤板祝。
上面兩種方法需要指定文檔id,ES還提供了基于search的update API走净,及update_by_query API券时。
姿勢3,使用update_by_query API
update_by_query API的第一種使用方式是什么都不指定伏伯,直接使用橘洞。
POST twitter/_update_by_query?conflicts=proceed
我一開始看到這種用法,覺得特別疑惑说搅,因為這樣做除了更新了版本號炸枣,似乎也沒有什么變化。后來讀了官方文檔才了解到這種用法的含義。
在設(shè)置索引配置的時候抛虏,有一個dynamic
屬性博其,如果設(shè)置成false的話套才,如果碰到?jīng)]有事先映射過的字段迂猴,是不會做索引,搜索不到的背伴。需要注意沸毁,是搜索不到,但不是沒有存儲傻寂,這個數(shù)據(jù)還是在的息尺。那怎樣能使得這個數(shù)據(jù)能夠被索引到呢,這個時候update_by_query就能排上用場了疾掰。我們先更新這個索引的mapping搂誉,然后調(diào)用update_by_query API。對應(yīng)的文檔會重新索引一次静檬,之前不能搜索的字段就變得能夠被搜索到了炭懊。
和query API一樣,update_by_query也可以擁有一個query塊拂檩,作為update的條件出現(xiàn):
POST twitter/_update_by_query
{
"script": {
"source": "ctx._source.likes++",
"lang": "painless"
},
"query": {
"term": {
"user": "kimchy"
}
}
}
同樣也可以使用painless進行update操作侮腹。
PUT _ingest/pipeline/set-foo
{
"description" : "sets foo",
"processors" : [ {
"set" : {
"field": "foo",
"value": "bar"
}
} ]
}
POST twitter/_update_by_query?pipeline=set-foo
在進行update_by_query的時候,還可以指定pipeline稻励,使用pipeline的處理器處理文檔父阻。
還有一些其他用法,可以參考官方文檔:
https://www.elastic.co/guide/en/elasticsearch/reference/7.2/docs-update-by-query.html