07.update和upsert操作

2024-08-31 15:58
文章标签 操作 update 07 upsert

本文主要是介绍07.update和upsert操作,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 1. Update API 简介
    • 2. 使用脚本更新
    • 3. 非script的部分文档更新
    • 4. 检测空操作更新 noop updates
    • 5. Upserts
      • 1. scripted_upsert
      • 2. doc_as_upsert
    • 6. 参数

1. Update API 简介

update API 允许基于script脚本来更新doc。对应的操作从index当中获取doc,然后run script, 然后再将修改后的doc indexing到原来的index。在这个过程中使用了version控制,以便于确保在获取和重新索引没有更新发生。

注意,此操作仍然意味着对文件做重新的全索引。它只是删除了一些网络往返,减少了在索引和获取时候版本冲突的几率。 _source需要启用此功能工作。

例如:一个简单的索引文件:

PUT test/_doc/1
{"counter" : 1,"tags" : ["red"]
}

2. 使用脚本更新

现在,我们可以执行一个脚本,用做计数器:

POST test/_update/1
{"script" : {"source": "ctx._source.counter += params.count","lang": "painless","params" : {"count" : 4}}
}

我们可以添加标签来进行标记(注意,如果标签存在,仍然会添加,因为是一个列表)

POST test/_update/1
{"script" : {"source": "ctx._source.tags.add(params.tag)","lang": "painless","params" : {"tag" : "blue"}}
}

我们可以从标签列表中删除标签。请注意,删除标签的painless的remove函数将要删除的元素的数组索引作为其参数,因此需要更多的逻辑来定位它,同时避免运行时错误。请注意,如果该标签在列表中出现多次,则只会删除一次该标签

POST test/_update/1
{"script" : {"source": "if (ctx._source.tags.contains(params.tag)) { ctx._source.tags.remove(ctx._source.tags.indexOf(params.tag)) }","lang": "painless","params" : {"tag" : "blue"}}
}

除了_source,下列变量通过 ctx map 都是可用的:_index,_type,_id,_version,_routing,_parent,和_now(当前的时间戳)。

我们也可以将新字段添加到文档:

POST test/_update/1
{"script" : "ctx._source.new_field = 'value_of_new_field'"
}

或者从文件中删除字段:

POST test/_update/1
{"script" : "ctx._source.remove('new_field')"
}

而且,我们甚至可以改变已执行的操作。这个例子就是如果 tags包含 green删除文档,否则就什么也不做(noop):

POST test/_update/1
{"script" : {"source": "if (ctx._source.tags.contains(params.tag)) { ctx.op = 'delete' } else { ctx.op = 'none' }","lang": "painless","params" : {"tag" : "green"}}
}

3. 非script的部分文档更新

更新 API 还支持部分文档的更新,将合并到现有的文件(简单的递归合并,内合并,更换核心“键/值”对和数组)。例如:

POST test/_update/1
{"doc" : {"name" : "new_name"}
}

如果同时 doc 和 script 被指定,那么 doc将被忽略。推荐的做法是使用script来update部分文档。

4. 检测空操作更新 noop updates

默认情况下回进行无更新检测,当要merged的doc片段和原有的doc中的字段是一致的话,不会有更新操作产生,在response当中会有一个"result": "noop"标识
比如下面的操作

POST test/_update/1
{"doc" : {"name" : "new_name"}
}

如果 name字段在这个秦秋之前就是 new_name,那么整个更新请求会被忽略。如果请求被忽略了,在 result响应中的返回 noop。

{"_shards": {"total": 0,"successful": 0,"failed": 0},"_index": "test","_type": "_doc","_id": "1","_version": 7,"result": "noop"
}

你可以通过设置 “detect_noop” 禁用此行为:

POST test/_update/1
{"doc" : {"name" : "new_name"},"detect_noop": false
}

5. Upserts

如果该文件存在,那么 script将执行。如果该文件不存在,则upsert内容将被插入作为一个新的文档。

POST test/_update/1
{"script" : {"source": "ctx._source.counter += params.count","lang": "painless","params" : {"count" : 4}},"upsert" : {"counter" : 1}
}

上面的请求如果_id为1的doc不存在的话,会插入一个文档,source中只有一个字段,是counter:1

1. scripted_upsert

如果你想你的脚本无论该文件存在与否都要运行-即脚本处理初始化文件而不是 upsert -然后设置 scripted_upsert为 true:

POST sessions/_update/dh3sgudg8gsrgl
{"scripted_upsert":true,"script" : {"id": "my_web_session_summariser","params" : {"pageViewEvent" : {"url":"foo.com/bar","response":404,"time":"2014-01-01 12:32"}}},"upsert" : {}
}

2. doc_as_upsert

doc 添加一个 upsert文档,设置 doc_as_upsert为 true ,将使用 doc 内容作为 upsert 值:

POST test/_update/1
{"doc" : {"name" : "new_name"},"doc_as_upsert" : true
}

6. 参数

更新操作支持以下查询字符串参数:

retry_on_conflict 在更新的 get 和 index 时,它可能是另一种方法可能已经更新了相同的文件。默认情况下,更新将失败,版本冲突异常。该 retry_on_conflict 参数控制抛出异常之前重试更新的次数。
routing 用于追踪更新请求正确的分片,如果文档更新不存在把其设置为更新插入请求。不能用于更新现有文档的路径。
timeout 超时等待一个分片变得可用。
wait_for_active_shards 在更新操作时,复制分片需要处在活跃状态的数目。
refresh 控制被该请求所做更改时进行的搜索。
_source 允许控制是否以及更新源如何在响应中返回。默认情况下不返回更新的源。见 source_filtering 详情。
version 更新 API 使用 Elasticsearch 的internal version。您可以使用 version 参数指定版本,如果文件匹配那么指定的文件需要更新。
if_seq_no and if_primary_term: 可以用来做并发控制,可以控制仅在文档的最后一次因为修改分配的_seq_no和_primary_term 参数和请求时传进来的if_seq_no和if_primary_term参数相等的情况下才能执行操作。如果检测到不匹配,则该操作将导致VersionConflictException和状态码409。

注意:
update api只支持internal version,External (version types external and external_gte) 是不支持的。

这篇关于07.update和upsert操作的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1124347

相关文章

动手学深度学习【数据操作+数据预处理】

import osos.makedirs(os.path.join('.', 'data'), exist_ok=True)data_file = os.path.join('.', 'data', 'house_tiny.csv')with open(data_file, 'w') as f:f.write('NumRooms,Alley,Price\n') # 列名f.write('NA

线程的四种操作

所属专栏:Java学习        1. 线程的开启 start和run的区别: run:描述了线程要执行的任务,也可以称为线程的入口 start:调用系统函数,真正的在系统内核中创建线程(创建PCB,加入到链表中),此处的start会根据不同的系统,分别调用不同的api,创建好之后的线程,再单独去执行run(所以说,start的本质是调用系统api,系统的api

Java IO 操作——个人理解

之前一直Java的IO操作一知半解。今天看到一个便文章觉得很有道理( 原文章),记录一下。 首先,理解Java的IO操作到底操作的什么内容,过程又是怎么样子。          数据来源的操作: 来源有文件,网络数据。使用File类和Sockets等。这里操作的是数据本身,1,0结构。    File file = new File("path");   字

MySQL——表操作

目录 一、创建表 二、查看表 2.1 查看表中某成员的数据 2.2 查看整个表中的表成员 2.3 查看创建表时的句柄 三、修改表 alter 3.1 重命名 rename 3.2 新增一列 add 3.3 更改列属性 modify 3.4 更改列名称 change 3.5 删除某列 上一篇博客介绍了库的操作,接下来来看一下表的相关操作。 一、创建表 create

封装MySQL操作时Where条件语句的组织

在对数据库进行封装的过程中,条件语句应该是相对难以处理的,毕竟条件语句太过于多样性。 条件语句大致分为以下几种: 1、单一条件,比如:where id = 1; 2、多个条件,相互间关系统一。比如:where id > 10 and age > 20 and score < 60; 3、多个条件,相互间关系不统一。比如:where (id > 10 OR age > 20) AND sco

PHP7扩展开发之流操作

前言 啥是流操作?简单来讲就是对一些文件,网络的IO操作。PHP已经把这些IO操作,封装成流操作。这节,我们将使用PHP扩展实现一个目录遍历的功能。PHP示例代码如下: <?phpfunction list_dir($dir) {if (is_dir($dir) === false) {return;} $dh = opendir($dir);if ($dh == false) {ret

浙大数据结构:树的定义与操作

四种遍历 #include<iostream>#include<queue>using namespace std;typedef struct treenode *BinTree;typedef BinTree position;typedef int ElementType;struct treenode{ElementType data;BinTree left;BinTre

浙大数据结构:04-树7 二叉搜索树的操作集

这道题答案都在PPT上,所以先学会再写的话并不难。 1、BinTree Insert( BinTree BST, ElementType X ) 递归实现,小就进左子树,大就进右子树。 为空就新建结点插入。 BinTree Insert( BinTree BST, ElementType X ){if(!BST){BST=(BinTree)malloc(sizeof(struct TNo

hibernate修改数据库已有的对象【简化操作】

陈科肇 直接上代码: /*** 更新新的数据并并未修改旧的数据* @param oldEntity 数据库存在的实体* @param newEntity 更改后的实体* @throws IllegalAccessException * @throws IllegalArgumentException */public void updateNew(T oldEntity,T newEntity

mysql中导入txt文件数据的操作指令

1 表tt的格式:    CREATE TABLE `tt` (   `ind` int NOT NULL auto_increment,   `name` char(100) default NULL,   PRIMARY KEY  (`ind`)  )   2 文件d.txt的内容示例:  1,a  2,b  3,c