登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  数据库 >  Redis

Redis JSON.SET 怎样只在键存在时更新

来源:17golang原创

时间:2026-10-23 04:40:24 173浏览 收藏

要让 Redis JSON.SET 只更新已有 JSON 文档,可以把路径设为根路径 $,并在末尾加 XX。但如果你更新的是 $.stock,XX 要求这个路径有匹配,不只是 Redis 键存在。把这两个条件混为一谈,很容易把“没有更新”误判成连接故障。

官方地址:https://redis.io/docs/latest/commands/json.set/

把“只更新已有文档”交给根路径 XX

# 在支持 JSON.SET 的测试实例执行;根路径替换整份文档,不是合并字段
redis-cli JSON.SET 'demo:jsonxx:catalog:166' '$' '{"name":"收纳袋","stock":18}' XX

这种写法适合“对象已建立,后续请求只能修改”的接口约束。新建由专门入口负责;更新入口不顺手补建数据。它的代价是根替换会丢掉新值未携带的旧字段,因此不能把一份不完整的表单当成完整文档提交。

本文命令是供读者在隔离测试环境尝试的原创示例,未在本机执行;后面的状态描述是按命令语义推导的预期,不是运行记录。

键存在,不等于目标字段存在

可以把条件拆成两个边界:Redis 键 demo:jsonxx:catalog:166 持有 JSON 文档;JSONPath $.stock 定位其中的成员。JSON.SET 将路径、值与 XX 条件放在同一条命令里。根路径 $ 对应整份文档,子路径对应字段。

JSON文档与更新条件的静态关系
静态结构图:文档边界区分键与 stock 成员,更新约束区说明路径和 XX 的关系;不是执行流程或运行截图。

例如文档只有 name,没有 stock:键确实存在,但 stock 路径没有匹配,JSON.SET key $.stock 18 XX 不会为它新增 stock。若业务允许给已有文档补一个新字段,就不能把“字段必须存在”当成同一个需求。不要为了得到 OK 而直接去掉 XX,因为键消失后的行为也需要重新设计。

用一个测试文档观察两种更新范围

# 仅在自己的隔离测试命名空间使用;NX 避免覆盖已有同名演示数据
redis-cli JSON.SET 'demo:jsonxx:catalog:166' '$' '{"name":"收纳袋","stock":18}' NX

# 如果上面的初始化未成功,先停止,不要继续修改未知旧数据
# 已有字段的局部更新:保留 name,只替换 stock
redis-cli JSON.SET 'demo:jsonxx:catalog:166' '$.stock' '21' XX

# 不允许新增未存在的 color 字段;预期为未命中条件
redis-cli JSON.SET 'demo:jsonxx:catalog:166' '$.color' '"blue"' XX

# 根路径替换:新文档只包含 stock,原 name 不会被自动保留
redis-cli JSON.SET 'demo:jsonxx:catalog:166' '$' '{"stock":24}' XX

# 读取供自己观察;带 $ 的查询返回匹配结果集合,不把外层数组误当成存储值
redis-cli JSON.GET 'demo:jsonxx:catalog:166' '$'

不要在生产键上照抄根替换。这里特意用不同数值与少量字段展示影响范围,不构造性能结论。字符串 "blue" 仍需作为有效 JSON 字符串传入;外层单引号供 shell 保留内部双引号。生产代码应让 JSON 序列化库编码值,不手工拼接用户输入。

XX 消除了存在性检查窗口,但不是版本锁

“先 EXISTS,再 JSON.SET”是一个容易出现的反例。两次独立请求之间,另一个客户端可能删掉键;更新者拿到的存在性结论已经过时。根路径 XX 将“根文档存在”和“替换根文档”表达为单条条件写入,避免依赖那次过时检查。

不过,XX 没有比较旧 stock,也没有核对文档版本。两个客户端都更新一个仍然存在的文档时,条件可以都成立。它不是防止覆盖的乐观锁,更不是“值和我刚才读到的一样才写”的保证。需要旧值比较或多条命令协同时,应另行设计条件更新机制,而不是在 XX 外面再加一层普通 EXISTS。

局部更新范围与存在性约束的静态说明
静态结构图:数据范围区对照根文档和 stock,条件含义区把 XX 与版本比较分开;连线表达约束归属,不表示先后顺序。

把未命中和执行错误分开处理

回执类别接口应怎样理解
OK命令接受了写入;不等于通过业务版本检查
空回复条件不满足等情况下没有写入,不能当成成功
错误回复排查 JSON、路径、类型和命令支持等问题,不与未命中混为一类

客户端对空回复的表示可能不同,按所用库的返回约定处理,别只比较屏幕上的 (nil) 字样。路径语法错误与不支持的路径情况也可能报错,不能概括成“所有路径问题都返回空”。

采用前只需把需求说清:是替换整份已有文档,还是仅更新已有字段;允许不允许新增成员;未命中由接口返回什么业务状态;是否还需要防止并发覆盖。XX 解决其中的存在性约束,不替代其他业务规则。

相关问题

用 SET 写进去的 JSON 字符串能直接当成 JSON 文档吗? 不要把字符串存储与 JSON 数据类型混用,按部署支持的 JSON 命令建模和初始化。

已有字段的值是 JSON null,算不存在吗? 存在性看路径是否匹配,不看值是否“有用”;业务要拒绝 null,需要另加业务约束。

XX 适合拿来首次创建文档吗? 不适合。创建和仅更新应分开定义,避免更新入口偷偷变成创建入口。

技术参考:Redis 官方 JSON.SET 命令说明。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>