redis8.0新特性:原生JSON支持详解

发布于:2025-06-26 ⋅ 阅读:(16) ⋅ 点赞:(0)

一、写在前面

官方文档:https://redis.io/docs/latest/commands/?group=json

关于在JSON命令中使用字符串:
若要将字符串指定为要追加的数组值,请用一组额外的单引号将带引号的字符串括起来。示例:‘“silver”’

JSONPATH语法:
Redis JSON 使用 $ 表示根节点,支持嵌套路径,例如:
$.user.address.city
$[0].name(访问数组第一个元素的 name 字段)

二、使用

1、基本命令

(1)JSON.SET 设置 JSON 值

# 格式
# key 是修改的key
# path:要指定的JSONPath。默认值是root$。对于新的Redis键path一定是根。对于现有键,当整个path存在,则它包含的值将被替换为json value。对于现有键,当path存在,但最后一个元素除外,则添加一个带有json 的value。
# NX:不存在时设置
# XX:存在时设置
JSON.SET key path value [NX | XX]
# 设置redis根的值
127.0.0.1:6379> JSON.SET doc $ '{"a":2}'
OK
127.0.0.1:6379> JSON.GET doc
"{\"a\":2}"
127.0.0.1:6379> JSON.GET doc $.a
"[2]"
# 往根添加另一个属性
127.0.0.1:6379> JSON.SET doc $.b '8'
OK
127.0.0.1:6379> JSON.GET doc
"{\"a\":2,\"b\":8}"
# 替换值
127.0.0.1:6379> JSON.SET doc $.a '3'
OK
127.0.0.1:6379> JSON.GET doc
"{\"a\":3,\"b\":8}"
# 没有才设置
127.0.0.1:6379> JSON.SET doc $.a '3' NX
(nil)
# 有才设置,直接替换
127.0.0.1:6379> JSON.SET doc $.a '3' XX
OK
# 设置多个值,会将root下都替换掉
127.0.0.1:6379> JSON.SET doc $ '{"f1": {"a":1}, "f2":{"a":2}}'
OK
# 设置所有的a的值为3
127.0.0.1:6379> JSON.SET doc $..a 3
OK
127.0.0.1:6379> JSON.GET doc
"{\"f1\":{\"a\":3},\"f2\":{\"a\":3}}"
# 路径不存在无法创建
redis> JSON.SET doc $ 1
OK
redis> JSON.SET doc $.x.y 2
(nil)
# 必须优先创建根json
127.0.0.1:6379> JSON.SET nonexistentkey $.x 5
(error) ERR new objects must be created at the root

(2)JSON.GET 获取 JSON 值

# 格式
# path:指定的JSONPath。默认值是root$。JSON。GET接受多个path参数
# INDENT 设置嵌套级别的缩进字符串。
# NEWLINE 设置打印在每行末尾的字符串。
# SPACE 设置放在键和值之间的字符串。
JSON.GET key [INDENT indent] [NEWLINE newline] [SPACE space] [path [path ...]]

# 格式化json字符串(貌似在cli命令行不太好使,应该是得--raw的事)
~/$ redis-cli --raw
redis> JSON.GET myjsonkey INDENT "\t" NEWLINE "\n" SPACE " " path.to.value[1]
127.0.0.1:6379> JSON.SET doc $ '{"a":2, "b": 3, "nested": {"a": 4, "b": null}}'
OK
# 单个jsonpath获取值
127.0.0.1:6379> JSON.GET doc $..b
"[3,null]"
# 多个jsonpath获取值,会返回一个JSON字符串,该字符串包含一个顶级对象,每个路径包含一个JSON值数组
127.0.0.1:6379> JSON.GET doc ..a $..b
"{\"..a\":[2,4],\"$..b\":[3,null]}"

(3)JSON.DEL 删除 JSON 值

# 语法
# path:要指定的JSONPath。默认值是root$。不存在的路径被忽略。
# 注意!删除json的根相当于删除整个key
JSON.DEL key [path]
127.0.0.1:6379> JSON.SET doc $ '{"a": 1, "nested": {"a": 2, "b": 3}}'
OK
# 根据jsonpath删除数据
127.0.0.1:6379> JSON.DEL doc $..a
(integer) 2
127.0.0.1:6379> JSON.GET doc $
"[{\"nested\":{\"b\":3}}]"

# 删除根,相当于删除整个key
127.0.0.1:6379> JSON.DEL doc $
(integer) 1
127.0.0.1:6379> JSON.GET doca $
(nil)

(4)JSON.MGET 批量获取

警告:
启用群集模式时,所有指定的键必须驻留在同一个散列槽。

# 语法
JSON.MGET key [key ...] path
redis> JSON.SET doc1 $ '{"a":1, "b": 2, "nested": {"a": 3}, "c": null}'
OK
redis> JSON.SET doc2 $ '{"a":4, "b": 5, "nested": {"a": 6}, "c": null}'
OK

# 从多个文档获取值
redis> JSON.MGET doc1 doc2 $..a
1) "[1,3]"
2) "[4,6]"

(5)JSON.MSET 批量插入

# 语法
# JSON.MSET是原子性的,因此,所有给定的添加或更新要么被应用,要么不被应用。客户端不可能看到一些密钥被更新,而另一些没有改变。
JSON.MSET key path value [key path value ...]
redis> JSON.MSET doc1 $ '{"a":1}' doc2 $ '{"f":{"a":2}}' doc3 $ '{"f1":{"a":0},"f2":{"a":0}}'
OK
redis> JSON.MSET doc1 $ '{"a":2}' doc2 $.f.a '3' doc3 $ '{"f1":{"a":1},"f2":{"a":2}}'
OK
redis> JSON.GET doc1 $
"[{\"a\":2}]"
redis> JSON.GET doc2 $
"[{\"f\":{\"a\":3}}]"
redis> JSON.GET doc3
"{\"f1\":{\"a\":1},\"f2\":{\"a\":2}}"

2、数组命令

(1)JSON.ARRAPPEND 数组追加元素

# 语法 追加到一个或多个数组中的一个或多个值。
# JSON.ARRAPPEND返回排列每个路径的整数回复数、数组的新大小或nil
JSON.ARRAPPEND key [path] value [value ...]
127.0.0.1:6379> JSON.SET doc $ '{"name":"zhangsan","age":15,"address":"shandong","like":["sing","read"]}'
OK
# 往数组中追加一个数据,返回值为数组追加后的长度
127.0.0.1:6379> JSON.ARRAPPEND doc $.like '"write"'
1) (integer) 3
127.0.0.1:6379> JSON.GET doc
"{\"name\":\"zhangsan\",\"age\":15,\"address\":\"shandong\",\"like\":[\"sing\",\"read\",\"write\"]}"
# 非数组无法追加,返回nil
127.0.0.1:6379> JSON.ARRAPPEND doc $.name '"lisi"'
1) (nil)

(2)JSON.ARRINSERT 数组插入元素

# 语法:在index之前插入数组元素
# value 要插入一个或多个数组中的一个或多个值。
# index 是数组中要插入值的位置。索引必须在数组的范围内。插入位置index0前置到数组。负索引值从数组的末尾开始。
JSON.ARRINSERT key path index value [value ...]
127.0.0.1:6379> JSON.SET doc $ '{"name":"zhangsan","age":15,"address":"shandong","like":["sing","read"]}'
OK
# 往数组中追加
127.0.0.1:6379> JSON.ARRAPPEND doc $.like '"write"'
1) (integer) 3
# 往数组中第二个索引位插入(从0开始计算)
127.0.0.1:6379> JSON.ARRINSERT doc $.like 2 '"run"' '"walk"'
1) (integer) 5
127.0.0.1:6379> JSON.GET doc
"{\"name\":\"zhangsan\",\"age\":15,\"address\":\"shandong\",\"like\":[\"sing\",\"read\",\"run\",\"walk\",\"write\"]}"

(3)JSON.ARRLEN 获取数组长度

# 语法
JSON.ARRLEN key [path]
127.0.0.1:6379> JSON.SET doc $ '{"name":"zhangsan","age":15,"address":"shandong","like":["sing","read"]}'
OK
# 获取所有对象的数组长度,如果不是数组则返回nil
127.0.0.1:6379> JSON.ARRLEN doc '$.[*]'
1) (nil)
2) (nil)
3) (nil)
4) (integer) 2
# 返回指定数组长度
127.0.0.1:6379> JSON.ARRLEN doc '$.like'
1) (integer) 2

(4)JSON.ARRINDEX 查找第一个索引

# 语法
# start:要在要搜索的数组片段中指定的起始值。默认值为0.
# stop:是要在要搜索的数组片段中指定的独占停止值,包括最后一个元素。默认值为0。负值被解释为从末尾开始。
#关于超出范围的索引:超出范围的索引舍入到数组的开头和结尾。反向索引范围(如从1到0的范围)返回unfound或-1.
JSON.ARRINDEX key path value [start [stop]]

# 实例
127.0.0.1:6379> JSON.SET doc $ '{"name":"zhangsan","age":15,"address":"shandong","like":["sing","read"]}'
OK
# 返回索引位置
127.0.0.1:6379> JSON.ARRINDEX doc $.like '"read"'
1) (integer) 1
127.0.0.1:6379> JSON.ARRINDEX doc $.like '"sing"'
1) (integer) 0
# 返回-1则表示未找到,nil表示不是数组
127.0.0.1:6379> JSON.ARRINDEX doc $.like '"run"'
1) (integer) -1

(5)JSON.ARRPOP 移出并返回元素

# 语法 从数组的索引中移除并返回一个元素
# index:是数组中开始弹出的位置。默认值为-1,意思是最后一个元素。超出范围的索引舍入到各自的数组末尾。弹出空数组会返回null。
JSON.ARRPOP key [path [index]]
127.0.0.1:6379> JSON.SET doc $ '{"name":"zhangsan","age":15,"address":"shandong","like":["sing","read"]}'
OK
# 数组第0个位置移出
127.0.0.1:6379> JSON.ARRPOP doc $.like 0
1) "\"sing\""
127.0.0.1:6379> JSON.GET doc
"{\"name\":\"zhangsan\",\"age\":15,\"address\":\"shandong\",\"like\":[\"read\"]}"
# 数组第0个位置插入,模拟了数组中数据的替换
127.0.0.1:6379> JSON.ARRINSERT doc $.like 0 '"run"'
1) (integer) 2
127.0.0.1:6379> JSON.GET doc
"{\"name\":\"zhangsan\",\"age\":15,\"address\":\"shandong\",\"like\":[\"run\",\"read\"]}"

(6)JSON.ARRTRIM 修剪数组

# 语法
# path:要指定的JSONPath。默认值是root$.
# start:是要保留的第一个元素的索引(前面的元素被修剪)。默认值为0。
# stop:是要保留的最后一个元素的索引(后面的元素被修剪),包括最后一个元素。默认值为0。负值被解释为从末尾开始。
JSON.ARRTRIM key path start stop

# 示例
127.0.0.1:6379> JSON.SET doc $ '{"name":"zhangsan","age":15,"address":"shandong","like":["sing","read","run","play"]}'
OK
127.0.0.1:6379> JSON.ARRTRIM doc $.like 1,3
(error) Couldn't parse as integer
# 修剪,保留1-3
127.0.0.1:6379> JSON.ARRTRIM doc $.like 1 3
1) (integer) 3
127.0.0.1:6379> JSON.GET doc
"{\"name\":\"zhangsan\",\"age\":15,\"address\":\"shandong\",\"like\":[\"read\",\"run\",\"play\"]}"

3、对象命令

(1)JSON.OBJKEYS 获取所有键

# 语法
JSON.OBJKEYS key [path]
127.0.0.1:6379> JSON.SET doc $ '{"a":[3], "nested": {"a": {"b":2, "c": 1}}}'
OK
# 获取指定path下所有的键
127.0.0.1:6379> JSON.OBJKEYS doc $..a
1) (nil)
2) 1) "b"
   2) "c"

(2)JSON.OBJLEN获取键数

# 语法
JSON.OBJLEN key [path]

# 实例
127.0.0.1:6379> JSON.SET doc $ '{"a":[3], "nested": {"a": {"b":2, "c": 1}}}'
OK
127.0.0.1:6379> JSON.OBJLEN doc $..a
1) (nil)
2) (integer) 2

4、数值操作

(1)JSON.NUMINCRBY增量操作

# 语法
# value:是要递增的数值。
JSON.NUMINCRBY key path value
127.0.0.1:6379> JSON.SET doc . '{"a":"b","b":[{"a":2}, {"a":5}, {"a":"c"}]}'
OK
# 找不到数字,返回null
127.0.0.1:6379> JSON.NUMINCRBY doc $.a 2
"[null]"
# 递归进行+2操作
127.0.0.1:6379> JSON.NUMINCRBY doc $..a 2
"[null,4,7,null]"
# 对指定数值+2
127.0.0.1:6379> JSON.NUMINCRBY doc $.b[0].a 2
"[6]"
127.0.0.1:6379> JSON.GET doc
"{\"a\":\"b\",\"b\":[{\"a\":6},{\"a\":7},{\"a\":\"c\"}]}"

(2)JSON.NUMMULTBY 乘法操作

# 语法
# value 是要相乘的数值。
JSON.NUMMULTBY key path value
127.0.0.1:6379> JSON.SET doc . '{"a":"b","b":[{"a":2}, {"a":5}, {"a":"c"}]}'
OK
# 非数字的无法相乘
127.0.0.1:6379> JSON.NUMMULTBY doc $.a 2
"[null]"
# 递归做乘法
127.0.0.1:6379> JSON.NUMMULTBY doc $..a 2
"[null,4,10,null]"

5、字符串操作

(1)JSON.STRAPPEND字符串追加

# 语法
#value 是要追加到一个或多个字符串的值。
JSON.STRAPPEND key [path] value

# 示例
redis> JSON.SET doc $ '{"a":"foo", "nested": {"a": "hello"}, "nested2": {"a": 31}}'
OK
redis> JSON.STRAPPEND doc $..a '"baz"'
1) (integer) 6
2) (integer) 8
3) (nil)
redis> JSON.GET doc $
"[{\"a\":\"foobaz\",\"nested\":{\"a\":\"hellobaz\"},\"nested2\":{\"a\":31}}]"

(2)JSON.STRLEN 获取字符串长度

# 语法
JSON.STRLEN key [path]

# 示例
redis> JSON.SET doc $ '{"a":"foo", "nested": {"a": "hello"}, "nested2": {"a": 31}}'
OK
redis> JSON.STRLEN doc $..a
1) (integer) 3
2) (integer) 5
3) (nil)

6、其他操作

(1)JSON.TYPE 获取类型

# 语法
# 如 object, array, string 等
JSON.TYPE key [path]
redis> JSON.SET doc $ '{"a":2, "nested": {"a": true}, "foo": "bar"}'
OK
redis> JSON.TYPE doc $..foo
1) "string"
redis> JSON.TYPE doc $..a
1) "integer"
2) "boolean"
redis> JSON.TYPE doc $..dummy
(empty array)

(2)JSON.CLEAR 清除数组/对象

# 语法 清除容器值(数组/对象)并将数值设置为0
JSON.CLEAR key [path]

# 示例
127.0.0.1:6379> JSON.SET doc $ '{"name":"zhangsan","age":15,"address":"shandong","like":["sing","read","run","play"]}'
OK
# 将like数组清空
127.0.0.1:6379> JSON.CLEAR doc $.like
(integer) 1
127.0.0.1:6379> JSON.GET doc
"{\"name\":\"zhangsan\",\"age\":15,\"address\":\"shandong\",\"like\":[]}"
# 对象无法清空
127.0.0.1:6379> JSON.CLEAR doc $.name
(integer) 0
127.0.0.1:6379> JSON.GET doc
"{\"name\":\"zhangsan\",\"age\":15,\"address\":\"shandong\",\"like\":[]}"
# 数值可以清空为0
127.0.0.1:6379> JSON.CLEAR doc $.*
(integer) 1
127.0.0.1:6379> JSON.GET doc
"{\"name\":\"zhangsan\",\"age\":0,\"address\":\"shandong\",\"like\":[]}"
# 根可以清空
127.0.0.1:6379> JSON.CLEAR doc $
(integer) 1
127.0.0.1:6379> JSON.GET doc
"{}"

(3)JSON.DEBUG MEMORY 查看内存

# 语法,返回一个整数,表示json占用的字节
JSON.DEBUG MEMORY key [path]

# 示例
127.0.0.1:6379> JSON.SET doc $ '{"name":"zhangsan","age":15,"address":"shandong","like":["sing","read","run","play"]}'
OK
127.0.0.1:6379> JSON.DEBUG MEMORY doc
(integer) 120

(4)JSON.MERGE 合并

# 语法
JSON.MERGE key path value

value:是指定路径中要合并的JSON值。其中的每个JSON值根据以下规则进行合并value参数,同时考虑相应的原始值(如果存在):
将现有的对象键与null值合并会删除
将现有对象键与非空值合并会更新该值
合并不存在的对象键会添加键和值
将现有数组与任何合并值合并,用该值替换整个数组

# 合并时创建不存在的key
redis> JSON.SET doc $ '{"a":2}'
OK
redis> JSON.MERGE doc $.b '8'
OK
redis> JSON.GET doc $
"[{\"a\":2,\"b\":8}]"
# 合并时替换
redis> JSON.SET doc $ '{"a":2}'
OK
redis> JSON.MERGE doc $.a '3'
OK
redis> JSON.GET doc $
"[{\"a\":3}]"
# 合并时删除
redis> JSON.SET doc $ '{"a":2}'
OK
redis> JSON.MERGE doc $ '{"a":null}'
OK
redis> JSON.GET doc $
"[{}]"
# 数组直接替换
redis> JSON.SET doc $ '{"a":[2,4,6,8]}'
OK
redis> JSON.MERGE doc $.a '[10,12]'
OK
redis> JSON.GET doc $
"[{\"a\":[10,12]}]"
# 多路径合并
redis> JSON.SET doc $ '{"f1": {"a":1}, "f2":{"a":2}}'
OK
redis> JSON.GET doc
"{\"f1\":{\"a\":1},\"f2\":{\"a\":2}}"
redis> JSON.MERGE doc $ '{"f1": null, "f2":{"a":3, "b":4}, "f3":[2,4,6]}'
OK
redis> JSON.GET doc
"{\"f2\":{\"a\":3,\"b\":4},\"f3\":[2,4,6]}"

(5)JSON.TOGGLE 切换布尔值

# 语法
JSON.TOGGLE key path

# 示例,切换布尔值
127.0.0.1:6379> JSON.SET doc $ '{"bool": true}'
OK
127.0.0.1:6379> JSON.TOGGLE doc $.bool
1) (integer) 0
127.0.0.1:6379> JSON.GET doc $
"[{\"bool\":false}]"
127.0.0.1:6379> JSON.TOGGLE doc $.bool
1) (integer) 1
127.0.0.1:6379> JSON.GET doc $
"[{\"bool\":true}]"


网站公告

今日签到

点亮在社区的每一天
去签到