局部更新document(partial updates to documents)

就像在Updating
a whole
document
中所说的一样,更新document的步骤就是检索——修改——插入整个document。然而使用update,就能局部更新,就像在一个请求里增加一个计数器一样。

以前说过document是不可变的——不能被修改,只能被替换,update也必须遵守这个规则。在外部看来是局部更新的,在内部,update依然执行了检索——修改——重新插入这个流程。不同的是这个过程是发生在shard中,因此避免了多次网络请求的开销,通过减少检索和重新插入的时间,降低了来自于其他线程的访问导致的数据冲突的可能性。

最简单的update格式就是请求体中接受部分的document作为“doc"的参数。这个参数的值会和已经存在的document合并,已经存在的field将会被重写,新的field将会被添加,例如,增加一个tags字段和一个views字段到blog中:

POST /website/blog/1/_update
{
   "doc":{
      "tags":["testing"],
      "views":0
   }
}

如果成功将会相应如下数据:

{
   "_index":   "website",
   "_id":      "1",
   "_type":    "blog",
   "_version":3
}

检索这个document,注意一下_source字段:

{
   "_index":    "website",
   "_type":     "blog",
   "_id":       "1",
   "_version":  3,
   "found":     true,
   "_source":{
      "title":  "My first blog entry",
      "text":   "Starting to get the hang of this...",
      "tags":["testing"],
      "views":  0
   }
}

标注1和2表示就是局部更新的内容。

使用script进行局部更新。我们会在 Scripting
– when you need more
(TODO)
更详细的介绍script,但是现在来说我们已经足够了解script在ES中的几个合适的用武之地,已满足某些不被API直接支持的但是用户需要的动作。默认的script语言是MVEL,但是ES也是支持JavaScript,Groovy和Python的。MVEL是简单的,快速的,基于jiava的动态脚本语言,语法类似于JavaScript。你可以在 Elasticsearch scripting docsMVEL website了解更过关于MVEL的内容。

script能用作update
API,用来修改_source的内容,这被称为一个更新的脚本ctx._source。例如,可以使用script增加这个views的数目:

POST /website/blog/1/_update
{
   "script":"ctx._source.views+=1"
}

我们也能使用script给tags数组增加一个元素,在这个例子中我们指定新的tag作为参数而不是在scritp中硬编码。这个方式允许ES在以后可以重用这个参数,并且不需要每次从新编译这个script:

POST /website/blog/1/_update
{
   "script":"ctx._source.tags+=new_tag",
   "params":{
      "new_tag":"search"
   }
}

最后两个的请求相应如下:

{
   "_index":    "website",
   "_type":     "blog",
   "_id":       "1",
   "_version":  5,
   "found":     true,
   "_source":{
      "title":  "My first blog entry",
      "text":   "Starting to get the hang of this...",
      "tags":  ["testing","search"],
      "views":  1
   }
}

标记1表示search这个元素已经追加到tags的数组中。

标记2表示views的数量已经增加了。

通过设置ctx.op为delete,我们甚至能通过script删除一个document。

POST /website/blog/1/_update
{
   "script":"ctx.op = ctx._source.views == count ? ‘delete‘ : ‘none‘",
    "params":{
        "count":1
    }
}

注:以上执行在curl下失败,在head中成功。

更新一个或许不存在的document

如果我们需要在ES中存储一个页面访问量的计数器conter,每次用户访问这个页面,我们都对这个页面增加一个数,但是增加这个counter之前要确定这个counter是已经存在的哦。如果要更新一个不存在的document,update将会出错。

可以使用upsert参数来解决这个问题,如果指定的document不存在,就创建一个:

POST /website/pageviews/1/_update
{
   "script":"ctx._source.views+=1",
   "upsert":{
       "views":1
   }
}

首次执行这个请求,这个upsert数值做为一个新的document被插入,被初始化为1。接下来的执行将会对views直接增加1。

更新和冲突

在本章节的说明部分,在检索和重新插入的间隔越小,冲突的机会就越小,但并不是完全没有冲突。依然有可能一个线程在另外一个线程执行update之前执行了reindex的动作。

为了防止这个事情的发生,updateAPI在执行检索的时候会检查记录document的_version的数量,并且在执行重新插入之间把_version传递给其他线程的index的请求。如果另外的线程在检索——重新插入之间修改了document,这个_version就不会和update记录的_version匹配导致update失败。

对于很多情况下的局部update来说,update并不关心一个document是否已经被修改,例如,两个线程同时增加页面的访问数量,以什么样的顺序发生update都是无所谓的——即使冲突发生了,唯一要做的事情就是重新执行update就行了。如果你在请求时候设置了retry_on_conflict参数并设定重复执行的次数(默认是0),这个重新执行就会自动进行:

POST /website/pageviews/1/_update?retry_on_conflict=5
{
   "script":"ctx._source.views+=1",
   "upsert":{
       "views":0
   }
}

标记1表示在成功更新之前尝试五次update。

这个设置对不强调顺序的多个线程无序的增加也个页面访问数量的值是很有效的,但是有另外的情况,就是更新的次序很重要。像index API,update
API就默认采用了”last-write-wins“这个办法,但是也能采用version参数,这个参数允许你使用 optimistic
concurrency control
 指定你要更新的document的version。

原文:http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/partial-updates.html

局部更新document(partial updates to documents),布布扣,bubuko.com

时间: 2024-08-24 05:49:20

局部更新document(partial updates to documents)的相关文章

Jquery Ajax 页面局部更新

Ajax 是一个异步过程,页面中的一部分代码发出一个网络请求,在里面设置一个回调函数,如果网络请求得到返回,那么执行回调函数.在回调函数中的上下文和时间触发的上下文会有所不同,在jquery中的应用需求大多数时候是这样的.比如我点击了一个按钮,这个按钮是一个 tr 中的 td 中的内容,我可以通过这个点击时间确定当前行的任何属性,或者确定当前也面中的任何一个属性,只要这个页面的布局是又某种可控的过滤的话.需要实用到this关键字.还有就是 find() 方法.比如this.parent().fi

经验总结16--EF局部更新数据

EF提供更新某个实体的某些数据,而其他数据保留的功能. 1.重新实例一个实体,并给予ID和需要修改的字段.注:此处的实体不能从数据库中查询,只能新的实例. Order order = new Order() { ID = id }; order.Name= "test222"; 2.包含该实体,更新策略为Unchanged,设置需要更新的字段. DbEntityEntry<Order> entry = db.Entry<Order>(order); entry.

部分更新document(pritial update document)

updateAPI是以前说过的read和write操作的联合: 操作步骤: 1:客户端向node1发起请求. 2:node1想node3转发请求,node3是要查找的document的primary shard被分配的地方 3:node3从primary shard检索要查找的document,把_source中的对应的field的作出修改,然后重新插入到priymary shard,如果document被其他线程进行了修改,那么根据retry_on_conflict指定的次数,重复步骤3直到失

ES使用脚本进行局部更新的排错记录

初学Elasticsearch,在按照<Elasticsearch服务器开发(第2版)>进行学习的过程中,在P17页中1.4.5 更新文档小节,使用脚本对文档进行局部更新的时候遇到了如下报错:   ~ curl -XPOST http://127.0.0.1:9200/blog/article/1/_update -d '{"script": "ctx._source.content=\"new content\""}' { &quo

【SSH网上商城项目实战28】使用Ajax技术局部更新商品数量和总价

昨天把项目部署了一下,玩了玩,今天完善了一下购物车中修改商品数量就能局部更新相应的总价的功能,大家都知道这得用Ajax实现,我之前也没学Ajax,刚好借助这个小功能,去简单学习一下Ajax的知识. 1.问题的分析 先看一下页面中的情况:  功能如上,在没有Ajax之前,一般都是根据用户修改的值去找Action,然后返回新的jsp页面重新加载整个页面,完成数字的更新.但是有了Ajax技术后,我们可以利用Ajax技术局部刷新要改变的地方,而不是重新加载整个页面.首先看一下上图对应的jsp部分的代码:

dojo组件使用---tree组件的局部更新

dojo的tree组件使用主要涉及的几个api: 1.dijit/Tree:树组件 2.dijit/Tree._TreeNode:树节点组件,局部更新时就是修改这个组件.(由于数组件的store使用Memory,所以需要手动同步更新store): 3.dijit/tree/ObjectStoreModel:数组件数据操作模块. 具体操作: 1.拿到dijit/Tree._TreeNode实例对象.树组件的每个节点都是一个dijit/Tree._TreeNode对象,通过selectedNode/

ASP.Net Core使用Ajax局部更新

由于目前ASP.NET Core中没有提供Ajax帮助器,所以参照 上一篇帖文,使用data-ajax-*属性来使用jQuery Unobtrusive Ajax功能实现HTML的局部页面元素更新. 在.cshtml文件中,根据文章分页,分别生成各页链接: <div id="content"> @if (Model.ContentArray.Count() > 1) { @Html.Raw(Model.ContentArray[0]) } else { @Html.R

使用ajax局部更新Razor页面

Razor功能非常强大,但是本身并不能做到无刷新,所以需要配合ajax使用 本文就做一个简单例子,实现Razor配合ajax做到局部刷新. 首先,我们创建一个MVC项目 让我们创建一个简单的Controller Book 然后对其添加一个视图,并且添加上一些简单的Html代码 1 @{ 2 ViewBag.Title = "Index"; 3 Layout = null; 4 } 5 <!DOCTYPE html> 6 <html> 7 <head>

ListView局部更新(非notifyDataSetChanged)

package com.example.test; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; import android.view.Menu; import android.view.Menu