# Update API

## 更新 API   

       更新 API 允许基于脚本文件来更新文件。操作允许从索引中获取文件（并行的分片）来运行脚本文件（带有可选择的脚本语言和参数），最终索引获得结果（允许删除和忽略该操作）。它使用版本控制，以便于确保在获取和重索引时候没有更新发生。

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

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

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

## 脚本更新

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

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

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

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

除了`_source`，下列变量通过 `ctx map 都是可用的`：`_index`，`_type`，`_id`，`_version`，`_routing`，`_parent`，和`_now`（当前的时间戳）。

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

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

或者从文件中删除字段：

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

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

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

## 部分文档更新

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

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

如果同时 `doc 和` `script 被`指定，那么 `doc `将被忽略。最好是把部分文件对应脚本本身。

检测空操作更新

如果 `doc `指定，它的值合并到现有的 `_source`。默认情况下不改变任何检测，他们不会改变任何并返回“结果”：“NOOP” 像这样的：

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

如果 `name `是 `new_name `请求，被发送之前那么整个更新请求被忽略。如果请求被忽略了在 `result `响应中的返回 `noop。`

```
{
   "_shards": {
        "total": 0,
        "successful": 0,
        "failed": 0
   },
   "_index": "test",
   "_type": "type1",
   "_id": "1",
   "_version": 6,
   "result": noop
}
```

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

```
POST test/type1/1/_update
{
    "doc" : {
        "name" : "new_name"
    },
    "detect_noop": true
}
```

## Upserts

如果该文件不存在，则内容`upsert`元素将被插入作为一个新的文档。如果该文件确实存在，那么 `script`将转而执行：

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

scripted_upsert

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

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

doc_as_upsert

取代发送部分 `doc 添加一个 ``upsert `文档，设置 `doc_as_upsert `为 `true ，`将使用 `doc 内容`作为 `upsert` 值：

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

## 参数

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

|   |   |
| --- | --- |
| retry_on_conflict | 在更新的 get 和 index 时，它可能是另一种方法可能已经更新了相同的文件。默认情况下，更新将失败，版本冲突异常。该 `retry_on_conflict` 参数控制抛出异常之前重试更新的次数。 |
| routing | 用于追踪更新请求正确的分片，如果文档更新不存在把其设置为更新插入请求。不能用于更新现有文档的路径。 |
| parent | 用于追踪更新请求正确的分片，如果文档更新不存在把 parent 设置为更新插入请求。不能用于更新 `parent` 现有文档的。如果被指定别名索引，那么它将覆盖父 route，它将用来 route 请求。 |
| timeout | 超时等待一个分片变得可用。 |
| wait_for_active_shards | 在更新操作时，复制分片需要处在活跃状态的数目。 |
| refresh | 控制被该请求所做更改时进行的搜索。 |
| _source | 允许控制是否以及更新源如何在响应中返回。默认情况下不返回更新的源。见 source_filtering 详情。 |
| `version` ＆`version_type` | 更新 API 使用 Elasticsearch 的版本控制以确保文件在更新过程中不会改变。您可以使用 `version` 参数指定版本，如果文件匹配那么指定的文件需要更新。通过设置版本类型 `force` ，你可以更新后迫使文件使用新版本（小心使用！`force` 不会保证该文件没有变化）。 |