Elasticsearch Document Update API详解、原理与示例

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: Elasticsearch Document Update API详解、原理与示例

本文将详细介绍单文档(Document)的更新API,其更新API如下:


  • public final UpdateResponse update(UpdateRequest updateRequest, RequestOptions options) throws IOException
  • public final void updateAsync(UpdateRequest updateRequest, RequestOptions options, ActionListener<UpdateResponse> listener)


重点关注UpdateRequest。


1、UpdateRequest详解


UpdateRequest的核心类图如图所示:

f8ff5b2efecd4219b8eb7074799647b3.jpg

我们首先来看一下UpdateRequest的核心属性:


  • protected ShardId shardId:指定需要执行的分片信息。
  • protected String index:索引库,类似于关系型数据库的数据库。
  • private String type:类型名,类似于关系数据库的表。
  • private String id :文档ID,类似于关系数据库的主键ID。
  • private String routing:分片值,默认为id的值,es的分片路由算法为( hashcode(routing) % primary_sharding_count)
  • private String parent:
  • Script script:通过脚步更新文档。
  • private String[] fields:需要返回的字段信息,默认为不返回,已废弃,被fetchSourceContext代替。
  • private FetchSourceContext fetchSourceContext:执行更新操作后,如果命中,需要返回_source的上下文配置,与fields的区别是fetchSourceContext支持通配符表达式来匹配字段名,已经在Elasticsearch Document Get API详解、原理与示例详细介绍过
  • private long version = Versions.MATCH_ANY:版本号
  • private VersionType versionType = VersionType.INTERNAL:版本类型,分为内部版本、外部版本,默认为内部版本。
  • private int retryOnConflict = 0:更新冲突时重试次数。
  • private RefreshPolicy refreshPolicy = RefreshPolicy.NONE:刷新策略。NONE:代表不重试;
  • private ActiveShardCount waitForActiveShards = ActiveShardCount.DEFAULT:执行操作之前需要等待激活的副本数,已在Elasticsearch Document Get API详解、原理与示例中详细介绍。
  • private IndexRequest upsertRequest:使用该 字段进行更新操作,如果原索引不存在,则更新,类似于saveOrUpdate操作,该操作需要与脚步执行,详细将在后续章节中描述,
  • private boolean scriptedUpsert = false;是否是用脚步执行更新操作。
  • private boolean docAsUpsert = false; 是否使用saveOrUpdate模式,即是否使用IndexRequest upsertRequest进行更新操作。(docAsUpser=true+ doc组合,将使用saveOrUpdate模式)。
  • private boolean detectNoop = true;是否检查空操作,下文会进行详细介绍。
  • private IndexRequest doc;默认使用该请求进行更新操作。

从上述我们基本可以得知更新基本有3种方式,script、upsert、doc(普通更新)。


2、深入分析Elasticsearch Update API(更新API)



2.1 Script脚步更新


Elasticsearch可以通过脚本(painless)进行更新,本节将不会深入去学习其语法,后续会看单独的章节对其进行详细讲解。


2.2 部分字段更新(普通更新方式)


更新API支持传递一个部分文档(_source字段中包含类型的部门字段),它将被合并到现有的文档中(简单的递归合并,对象的内部合并,替换核心的“键/值”和数组)。如果需要完全替代现有的文档,请使用(Index API)。以下部分更新为现有文档添加了一个新字段:(下文会给出基于java的API调用)。

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

如果指定了doc和script,则script属性优先,关于更新API一个比较好的实践是使用脚步更新(painless),后续会重点章节详细介绍。


2.3 检测空更新(检测本请求是否值得更新)


该功能特性的意思是当提交的请求,发现与原文档的数据并未发送变化,是否执行update操作,默认检测。如果开启检测,detectNoop=true,如果检测到数据并未发生变化,则返回结果为noop(空操作),如果detectNoop=false,每次操作都会执行,版本号将自增。


2.4 保存或更新(Upserts)


如果文档还不存在,upsert元素的内容将作为新文档插入。Elasticsearch支持scripted_upsert和doc_as_upsert两种模式,以scripted_upsert优先。通过UpdateRequest#scriptedUpsert和UpdateRequest#docAsUpsert控制。


2.5 核心参数一览表


更新API主要核心参数一览表:

image.png

注意:更新API不支持除内部以外的版本控制,外部(版本类型外部和外部的)或强制(版本类型的force)版本控制不受更新API的支持,因为它会导致弹性搜索版本号与外部系统不同步。


3、Update API使用示例


本节将暂时不会展示使用脚步进行更新的Demo,此部分会在后续文章中单独的章节来介绍ElasticSearch painless Script。


3.1 常规更新(更新部分字段)


public static void testUpdate_partial() {
        RestHighLevelClient client = EsClient.getClient();
        try {
            UpdateRequest request = new UpdateRequest("twitter", "_doc", "10");
            IndexRequest indexRequest = new IndexRequest("twitter", "_doc", "10");
            Map<String, String> source = new HashMap<>();
            source.put("user", "dingw2");
            indexRequest.source(source);
            request.doc(indexRequest);
            UpdateResponse result = client.update(request, RequestOptions.DEFAULT);
            System.out.println(result);
            testGet();
        } catch (Throwable e) {
            e.printStackTrace();
        } finally {
            EsClient.close(client);
        }
    }

最终结果:调用get API能反映出user字段已经更新为dingw2,及更新成功。


3.2 开启detectNoop示例(并且不改变原始数据)


public static void testUpdate_noop() {
        RestHighLevelClient client = EsClient.getClient();
        try {
            UpdateRequest request = new UpdateRequest("twitter", "_doc", "10");
            request.detectNoop(true);
            request.doc(buildIndexRequest());
            UpdateResponse result = client.update(request, RequestOptions.DEFAULT);
            System.out.println(result);
        } catch (Throwable e) {
            e.printStackTrace();
        } finally {
            EsClient.close(client);
        }
    }

返回结果:

{
   "_shards": {
        "total": 0,
        "successful": 0,
        "failed": 0
   },
   "_index": "twitter",
   "_type": "_doc",
   "_id": "10",
   "_version": 6,
   "result": "noop"
}


3.3不开启detectNoop示例(并且不改变原始数据)


public static void testUpdate_no_noop() {
        RestHighLevelClient client = EsClient.getClient();
        try {
            UpdateRequest request = new UpdateRequest("twitter", "_doc", "10");
            request.detectNoop(false);
            request.doc(buildIndexRequest());
            UpdateResponse result = client.update(request, RequestOptions.DEFAULT);
            System.out.println(result);
        } catch (Throwable e) {
            e.printStackTrace();
        } finally {
            EsClient.close(client);
        }
    }

返回结果:

{
   "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
   },
   "_index": "twitter",
   "_type": "_doc",
   "_id": "10",
   "_version": 7,
   "result": "updated"
}

其主要特征表现为result=updated,表示执行的动作为更新,并且版本号自增1,_shards反馈的是各分片的执行情况。


3.4 saveOrUpdate更新模式(upsert)


/**
     * 更新操作,原记录不存在,使用saveOrUpdate模式。
     */
    public static void testUpdate_upsert() {
        RestHighLevelClient client = EsClient.getClient();
        try {
            UpdateRequest request = new UpdateRequest("twitter", "_doc", "11");
            IndexRequest indexRequest = new IndexRequest("twitter", "_doc", "11");
            Map<String, String> source = new HashMap<>();
            source.put("user", "dingw");
            source.put("post_date", "2009-11-17T14:12:12");
            source.put("message", "hello,update upsert。");
            indexRequest.source(source);
            request.doc(indexRequest);
            request.docAsUpsert(true);
            UpdateResponse result = client.update(request, RequestOptions.DEFAULT);
            System.out.println(result);
        } catch (Throwable e) {
            e.printStackTrace();
        } finally {
            EsClient.close(client);
        }
    }

返回结果:

/**
     * 更新操作,原记录不存在,使用saveOrUpdate模式。
     */
    public static void testUpdate_upsert() {
        RestHighLevelClient client = EsClient.getClient();
        try {
            UpdateRequest request = new UpdateRequest("twitter", "_doc", "11");
            IndexRequest indexRequest = new IndexRequest("twitter", "_doc", "11");
            Map<String, String> source = new HashMap<>();
            source.put("user", "dingw");
            source.put("post_date", "2009-11-17T14:12:12");
            source.put("message", "hello,update upsert。");
            indexRequest.source(source);
            request.doc(indexRequest);
            request.docAsUpsert(true);
            UpdateResponse result = client.update(request, RequestOptions.DEFAULT);
            System.out.println(result);
        } catch (Throwable e) {
            e.printStackTrace();
        } finally {
            EsClient.close(client);
        }
    }

返回结果:

{
   "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
   },
   "_index": "twitter",
   "_type": "_doc",
   "_id": "11",
   "_version": 1,
   "result": "created"
}

返回结果其核心表现为:result:created,表示是一个新增操作。


Document API就讲解到这里了,本节详细介绍了Document Update  API的核心关键点以及实现要点,最后给出Demo展示如何在JAVA中使用Update API。

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
10天前
|
存储 人工智能 API
(Elasticsearch)使用阿里云 infererence API 及 semantic text 进行向量搜索
本文展示了如何使用阿里云 infererence API 及 semantic text 进行向量搜索。
|
1月前
|
监控 API 索引
Elasticsearch集群使用 _cluster/health API
Elasticsearch集群使用 _cluster/health API
55 2
|
1月前
|
Unix API 索引
Elasticsearch集群使用 _cat/health API
Elasticsearch集群使用 _cat/health API
34 1
|
1月前
|
存储 安全 数据管理
如何在 Rocky Linux 8 上安装和配置 Elasticsearch
本文详细介绍了在 Rocky Linux 8 上安装和配置 Elasticsearch 的步骤,包括添加仓库、安装 Elasticsearch、配置文件修改、设置内存和文件描述符、启动和验证 Elasticsearch,以及常见问题的解决方法。通过这些步骤,你可以快速搭建起这个强大的分布式搜索和分析引擎。
54 5
|
2月前
|
存储 JSON Java
elasticsearch学习一:了解 ES,版本之间的对应。安装elasticsearch,kibana,head插件、elasticsearch-ik分词器。
这篇文章是关于Elasticsearch的学习指南,包括了解Elasticsearch、版本对应、安装运行Elasticsearch和Kibana、安装head插件和elasticsearch-ik分词器的步骤。
232 0
elasticsearch学习一:了解 ES,版本之间的对应。安装elasticsearch,kibana,head插件、elasticsearch-ik分词器。
|
3月前
|
NoSQL 关系型数据库 Redis
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
mall在linux环境下的部署(基于Docker容器),docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongodb、minio详细教程,拉取镜像、运行容器
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
|
4月前
|
数据可视化 Docker 容器
一文教会你如何通过Docker安装elasticsearch和kibana 【详细过程+图解】
这篇文章提供了通过Docker安装Elasticsearch和Kibana的详细过程和图解,包括下载镜像、创建和启动容器、处理可能遇到的启动失败情况(如权限不足和配置文件错误)、测试Elasticsearch和Kibana的连接,以及解决空间不足的问题。文章还特别指出了配置文件中空格的重要性以及环境变量中字母大小写的问题。
一文教会你如何通过Docker安装elasticsearch和kibana 【详细过程+图解】
|
4月前
|
JSON 自然语言处理 数据库
Elasticsearch从入门到项目部署 安装 分词器 索引库操作
这篇文章详细介绍了Elasticsearch的基本概念、倒排索引原理、安装部署、IK分词器的使用,以及如何在Elasticsearch中进行索引库的CRUD操作,旨在帮助读者从入门到项目部署全面掌握Elasticsearch的使用。
|
4月前
|
Ubuntu Oracle Java
如何在 Ubuntu VPS 上安装 Elasticsearch
如何在 Ubuntu VPS 上安装 Elasticsearch
59 0
|
4月前
|
存储 Ubuntu Oracle
在Ubuntu 14.04上安装和配置Elasticsearch的方法
在Ubuntu 14.04上安装和配置Elasticsearch的方法
50 0