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 条件放在同一条命令里。根路径 $ 对应整份文档,子路径对应字段。

例如文档只有 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。

把未命中和执行错误分开处理
| 回执类别 | 接口应怎样理解 |
|---|---|
| OK | 命令接受了写入;不等于通过业务版本检查 |
| 空回复 | 条件不满足等情况下没有写入,不能当成成功 |
| 错误回复 | 排查 JSON、路径、类型和命令支持等问题,不与未命中混为一类 |
客户端对空回复的表示可能不同,按所用库的返回约定处理,别只比较屏幕上的 (nil) 字样。路径语法错误与不支持的路径情况也可能报错,不能概括成“所有路径问题都返回空”。
采用前只需把需求说清:是替换整份已有文档,还是仅更新已有字段;允许不允许新增成员;未命中由接口返回什么业务状态;是否还需要防止并发覆盖。XX 解决其中的存在性约束,不替代其他业务规则。
相关问题
用 SET 写进去的 JSON 字符串能直接当成 JSON 文档吗? 不要把字符串存储与 JSON 数据类型混用,按部署支持的 JSON 命令建模和初始化。
已有字段的值是 JSON null,算不存在吗? 存在性看路径是否匹配,不看值是否“有用”;业务要拒绝 null,需要另加业务约束。
XX 适合拿来首次创建文档吗? 不适合。创建和仅更新应分开定义,避免更新入口偷偷变成创建入口。
技术参考:Redis 官方 JSON.SET 命令说明。
-
236 收藏
-
313 收藏
-
484 收藏
-
104 收藏
-
463 收藏
-
166 收藏
-
250 收藏
-
204 收藏
-
244 收藏
-
458 收藏
-
306 收藏
-
146 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习