如何限制Elasticsearch文档中的指定字段不被更新
Elasticsearch 实现指定字段禁止更新的方案
完全可以实现该需求,核心通过Elasticsearch 摄取管道(Ingest Pipeline)结合脚本校验实现,仅拦截指定字段的更新操作,其余字段更新不受影响。
前置调整
你当前的索引模板配置中"_source": {"enabled": false}会导致无法读取已有文档的原始字段值做对比,必须先修改为开启状态,否则校验逻辑无法生效。
具体实现步骤
1. 更新索引模板
修改后的索引模板如下,新增默认摄取管道配置,同时开启_source:
PUT /_index_template/example_template { "index_patterns": [ "example*" ], "priority": 1, "template": { "aliases": { "example":{} }, "settings": { "index.default_pipeline": "block_someid_update" }, "mappings": { "dynamic":"strict", "_source": { "enabled": true }, "properties": { "SomeId": { "type": "keyword" }, "AnotherInfo": { "type": "keyword" } } } } }
注意:调整字段名大小写为统一的
SomeId,避免大小写不一致导致校验失效。
2. 创建校验用摄取管道
执行以下命令创建用于拦截SomeId更新的管道:
PUT _ingest/pipeline/block_someid_update { "description": "禁止更新文档的SomeId字段", "processors": [ { "script": { "source": """ // 仅校验已有文档的更新场景 if (ctx._op_type == 'index' && ctx._id != null) { Map existingDoc = null; try { // 查询同_id的已有文档 existingDoc = elasticsearch.get( 'index': ctx._index, 'id': ctx._id, 'fields': ['SomeId'], 'ignore': 404 ); } catch (Exception e) { // 文档不存在属于首次写入,直接跳过校验 return; } if (existingDoc != null && existingDoc.fields != null) { def oldSomeId = existingDoc.fields.SomeId; def newSomeId = ctx.SomeId; if (oldSomeId != null && newSomeId != null && !oldSomeId.equals(newSomeId)) { throw new IllegalArgumentException("抱歉,SomeId字段不可更新"); } } } """ } } ] }
效果验证
- 首次写入
_id=1的文档时,无匹配的已有文档,校验逻辑自动跳过,写入正常 - 再次写入同_id文档时如果修改了
SomeId的值,Elasticsearch会返回400异常,提示抱歉,SomeId字段不可更新 - 仅修改
AnotherInfo等其他字段时,校验逻辑会放行,更新操作正常执行
内容的提问来源于stack exchange,提问作者Nishikant Tayade
相关产品推荐
相关产品推荐

