elasticsearch更新文档数据

本文深入探讨了前端开发的关键技术和实战经验,从HTML、CSS、JavaScript等基础到Vue、React等现代框架,全面覆盖前端开发的最新趋势和最佳实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文本方式批量更新多字段

使用更新请求最简单的一种用途就是添加新数据。新的数据会被合并到现有数据中,而如果存在相同的字段,就会被新的数据所替换。例如我们可以为我们的博客添加tagsviews字段:

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

如果请求成功,我们就会收到一个类似于索引时返回的内容

使用脚本进行更新
默认的脚本语言叫做MVEL,但是Elasticsearch也支持JavaScript, Groovy 以及 Python。MVEL是一个简单高效的JAVA基础动态脚本语言,它的语法类似于Javascript。

脚本语言可以在更新API中被用来修改_source中的内容,而它在脚本中被称为ctx._source。例如,我们可以使用脚本来增加博文中views的数字:

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

我们同样可以使用脚本在tags数组中添加新的tag。在这个例子中,我们把新的tag声明为一个变量,而不是将他写死在脚本中。这样Elasticsearch就可以重新使用这个脚本进行tag的添加,而不用再次重新编写脚本了:

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"], <1>
      "views":  1 <2>
   }
}
  1. tags数组中出现了search
  2. views字段增加了。

我们甚至可以使用ctx.op来根据内容选择是否删除一个文档:

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

更新一篇可能不存在的文档

想象一下,我们可能需要在Elasticsearch中存储一个页面计数器。每次用户访问这个页面,我们就增加一下当前页面的计数器。但是如果这是个新的页面,我们不能确保这个计数器已经存在。如果我们试着去更新一个不存在的文档,更新操作就会失败。

为了防止上述情况的发生,我们可以使用upsert参数来设定文档不存在时,它应该被创建:

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

首次运行这个请求时,upsert的内容会被索引成新的文档,它将views字段初始化为1。当之后再请求时,文档已经存在,所以脚本更新就会被执行,views计数器就会增加。

为了避免丢失数据,更新API会在获取步骤中获取当前文档中的_version,然后将其传递给重新索引步骤中的索引请求。如果其他的进程在这两部之间修改了这个文档,那么_version就会不同,这样更新就会失败。

对于很多的局部更新来说,文档有没有发生变化实际上是不重要的。例如,两个进程都要增加页面浏览的计数器,谁先谁后其实并不重要 —— 发生冲突时只需要重新来过即可。

你可以通过设定retry_on_conflict参数来设置自动完成这项请求的次数,它的默认值是0

POST /website/pageviews/1/_update?retry_on_conflict=5 <1>
{
   "script" : "ctx._source.views+=1",
   "upsert": {
       "views": 0
   }
}
  1. 失败前重新尝试5次
这个参数非常适用于类似于增加计数器这种无关顺序的请求


<think>嗯,用户遇到了Elasticsearch更新文档数据不实时刷新的问题。根据他们提供的引用内容,特别是引用[2]提到的,es在更新后有1秒的延迟,这可能导致新增、删除或更新文档不能立即被查询到。首先,我需要回忆一下Elasticsearch的刷新机制。默认情况下,ES有一个刷新间隔,通常是1秒,这意味着数据写入后不会立即生成新的segment,从而对搜索可见。用户可能希望实时性更高的场景下,这个延迟就成了问题。 解决方案可能包括调整刷新间隔、手动触发刷新,或者使用其他机制如获取操作后的数据。比如,设置`refresh=true`在写入请求中,或者缩短索引的`refresh_interval`。不过,调整刷新间隔可能会影响性能,因为频繁的刷新会增加I/O负担。此外,用户还可以在写入后立即调用`_refresh` API,但这同样不推荐在高频写入中使用。 另外,可能用户的应用场景需要近实时搜索,这时候可以结合使用`_wait_for`参数,或者利用版本号检查。还有,在查询时使用`preference`参数,确保读取的是最新的数据。但需要注意,这些方法可能会增加响应时间或者资源消耗。 需要确保用户了解每种解决方案的优缺点,比如性能和实时性之间的权衡。另外,是否在写入操作后需要立即读取数据,比如前端展示,这时候可能需要结合应用层面的处理,比如直接返回写入结果,而不是立即查询ES。或者使用实时GET请求,因为ES的GET操作是实时的,即使搜索还未刷新。 可能用户没有考虑到GET请求和Search请求的区别,所以需要解释这两者的不同,以及如何利用GET来立即获取更新文档。此外,可能存在的误区是认为所有操作都应该立即可见,但实际上ES的设计是为了高吞吐量,因此需要根据具体需求调整参数。 最后,需要提醒用户测试不同方案在具体场景下的影响,确保不会因为过度调整刷新策略而导致集群性能下降。总结起来,解决方案应涵盖参数调整、手动刷新、实时GET和使用版本控制等方法,并权衡各自的利弊。</think>### Elasticsearch 更新文档数据不实时刷新的解决方案 #### 1. **调整刷新间隔(`refresh_interval`)** 默认情况下,Elasticsearch 每隔 **1秒** 自动刷新索引,使新写入的文档对搜索可见[^2]。若需缩短延迟,可动态调整索引的刷新间隔: ```json PUT /your_index/_settings { "index": { "refresh_interval": "500ms" // 缩短至500毫秒 } } ``` **注意**:频繁刷新会增加 I/O 压力,可能影响写入性能,需根据集群负载权衡[^1]。 --- #### 2. **强制立即刷新(手动触发)** 在关键操作(如新增、更新文档)后,调用 `_refresh` API 强制刷新索引: ```json POST /your_index/_refresh // 刷新指定索引 ``` 或在写入请求中添加 `refresh=true` 参数: ```json PUT /your_index/_doc/1?refresh=true { "field": "value" } ``` **缺点**:高频使用可能导致性能瓶颈,建议仅用于关键业务场景。 --- #### 3. **使用 `wait_for` 参数保证可见性** 在写入操作时,通过 `wait_for` 参数要求 ES 等待刷新完成后再返回响应: ```json POST /your_index/_doc?refresh=wait_for { "field": "value" } ``` 此方法平衡了实时性和性能,适用于需要保证数据立即可见的场景[^1]。 --- #### 4. **实时获取文档(GET 代替 Search)** Elasticsearch 的 **GET 请求**(如 `_doc` 接口)直接读取存储引擎,无需等待刷新: ```json GET /your_index/_doc/1 // 实时获取文档 ``` 而 **Search 请求**依赖索引刷新机制,因此若需立即读取数据,优先使用 GET 方法[^2]。 --- #### 5. **优化事务日志(Translog)持久化** 通过设置 `index.translog.durability` 为 `request`,确保每次操作后事务日志同步到磁盘: ```json PUT /your_index/_settings { "index": { "translog.durability": "request" } } ``` 此配置牺牲部分写入速度换取更高的数据可靠性,间接减少读取延迟[^1]。 --- #### 6. **使用版本号验证更新** 在应用层通过文档版本号(`_version`)判断更新是否生效: ```json PUT /your_index/_doc/1?version=2 { "field": "new_value" } ``` 若版本号冲突,则重试读取操作,确保最终一致性。 --- ### 性能与实时性权衡建议 | 方案 | 实时性 | 性能影响 | 适用场景 | |---------------------|--------|----------|------------------------| | 调整 `refresh_interval` | 高 | 中 | 近实时搜索需求 | | 手动刷新 | 最高 | 高 | 关键业务操作 | | `refresh=wait_for` | 中 | 低 | 平衡型场景 | | GET 代替 Search | 最高 | 低 | 单文档实时查询 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值