Appearance
JSON 格式
Redis 的 JSON 支持
Redis Stack 的 JSON 功能为 Redis 提供 JavaScript 对象表示法 (JSON) 支持。它允许您在 Redis 数据库中存储、更新和检索 JSON 值,类似于任何其他 Redis 数据类型。Redis JSON 还可以与 Redis 查询引擎无缝协作,让您能够为 JSON 文档编制索引和查询。
主要特点
- 完全支持 JSON 标准
- 用于选择/更新文档内元素的 JSONPath 语法(请参阅 JSONPath 语法)
- 文档以树状结构存储为二进制数据,允许快速访问子元素
- 所有 JSON 值类型的类型化原子操作
将 Redis 与 JSON 结合使用
要尝试的第一个 JSON 命令是 JSON。SET,它使用 JSON 值设置 Redis 密钥。JSON 的 JSON 格式。SET 接受所有 JSON 值类型。此示例创建一个 JSON 字符串:
bash
> JSON.SET bike $ '"Hyperion"'
OK
> JSON.GET bike $
"[\"Hyperion\"]"
> JSON.TYPE bike $
1) "string"
python
res1 = r.json().set("bike", "$", '"Hyperion"')
print(res1) # >>> True
res2 = r.json().get("bike", "$")
print(res2) # >>> ['"Hyperion"']
res3 = r.json().type("bike", "$")
print(res3) # >>> ['string']
js
const res1 = await client.json.set("bike", "$", '"Hyperion"');
console.log(res1); // OK
const res2 = await client.json.get("bike", "$");
console.log(res2); // "Hyperion"
const res3 = await client.json.type("bike", "$");
console.log(res3); // [ 'string' ]
java
String res1 = jedis.jsonSet("bike", new Path2("$"), "\"Hyperion\"");
System.out.println(res1); // >>> OK
Object res2 = jedis.jsonGet("bike", new Path2("$"));
System.out.println(res2); // >>> ["Hyperion"]
List<Class<?>> res3 = jedis.jsonType("bike", new Path2("$"));
System.out.println(res3); // >>> [class java.lang.String]
go
res1, err := rdb.JSONSet(ctx, "bike", "$",
"\"Hyperion\"",
).Result()
if err != nil {
panic(err)
}
fmt.Println(res1) // >>> OK
res2, err := rdb.JSONGet(ctx, "bike", "$").Result()
if err != nil {
panic(err)
}
fmt.Println(res2) // >>> ["Hyperion"]
res3, err := rdb.JSONType(ctx, "bike", "$").Result()
if err != nil {
panic(err)
}
fmt.Println(res3) // >>> [[string]]
csharp
bool res1 = db.JSON().Set("bike", "$", "\"Hyperion\"");
Console.WriteLine(res1); // >>> True
RedisResult res2 = db.JSON().Get("bike", path: "$");
Console.WriteLine(res2); // >>> ["Hyperion"]
JsonType[] res3 = db.JSON().Type("bike", "$");
Console.WriteLine(string.Join(", ", res3)); // >>> STRING
请注意这些命令如何包含美元符号$
。这是 JSON 文档中值的路径(在本例中,它仅表示根)。
下面是一些其他字符串操作。JSON.STRLEN
告诉您字符串的长度,您可以使用JSON.STRAPPEND
将另一个字符串附加到该字符串。
bash
> JSON.STRLEN bike $
1) (integer) 8
> JSON.STRAPPEND bike $ '" (Enduro bikes)"'
1) (integer) 23
> JSON.GET bike $
"[\"Hyperion (Enduro bikes)\"]"
python
res4 = r.json().strlen("bike", "$")
print(res4) # >>> [10]
res5 = r.json().strappend("bike", '" (Enduro bikes)"')
print(res5) # >>> 27
res6 = r.json().get("bike", "$")
print(res6) # >>> ['"Hyperion"" (Enduro bikes)"']
js
const res4 = await client.json.strLen("bike", "$");
console.log(res4) // [10]
const res5 = await client.json.strAppend("bike", '" (Enduro bikes)"');
console.log(res5) // 27
const res6 = await client.json.get("bike", "$");
console.log(res6) // ['"Hyperion"" (Enduro bikes)"']
java
List<Long> res4 = jedis.jsonStrLen("bike", new Path2("$"));
System.out.println(res4); // >>> [8]
List<Long> res5 = jedis.jsonStrAppend("bike", new Path2("$"), " (Enduro bikes)");
System.out.println(res5); // >>> [23]
Object res6 = jedis.jsonGet("bike", new Path2("$"));
System.out.println(res6); // >>> ["Hyperion (Enduro bikes)"]
go
res4, err := rdb.JSONStrLen(ctx, "bike", "$").Result()
if err != nil {
panic(err)
}
fmt.Println(*res4[0]) // >>> 8
res5, err := rdb.JSONStrAppend(ctx, "bike", "$", "\" (Enduro bikes)\"").Result()
if err != nil {
panic(err)
}
fmt.Println(*res5[0]) // >>> 23
res6, err := rdb.JSONGet(ctx, "bike", "$").Result()
if err != nil {
panic(err)
}
fmt.Println(res6) // >>> ["Hyperion (Enduro bikes)"]
csharp
bool res7 = db.JSON().Set("crashes", "$", 0);
Console.WriteLine(res7); // >>> True
double?[] res8 = db.JSON().NumIncrby("crashes", "$", 1);
Console.WriteLine(res8); // >>> 1
double?[] res9 = db.JSON().NumIncrby("crashes", "$", 1.5);
Console.WriteLine(res9); // >>> 2.5
double?[] res10 = db.JSON().NumIncrby("crashes", "$", -0.75);
Console.WriteLine(res9); // >>> 1.75
数字可以递增和相乘:
bash
> JSON.SET crashes $ 0
OK
> JSON.NUMINCRBY crashes $ 1
"[1]"
> JSON.NUMINCRBY crashes $ 1.5
"[2.5]"
> JSON.NUMINCRBY crashes $ -0.75
"[1.75]"
> JSON.NUMMULTBY crashes $ 24
"[42]"
python
res7 = r.json().set("crashes", "$", 0)
print(res7) # >>> True
res8 = r.json().numincrby("crashes", "$", 1)
print(res8) # >>> [1]
res9 = r.json().numincrby("crashes", "$", 1.5)
print(res9) # >>> [2.5]
res10 = r.json().numincrby("crashes", "$", -0.75)
print(res10) # >>> [1.75]
js
const res7 = await client.json.set("crashes", "$", 0);
console.log(res7) // OK
const res8 = await client.json.numIncrBy("crashes", "$", 1);
console.log(res8) // [1]
const res9 = await client.json.numIncrBy("crashes", "$", 1.5);
console.log(res9) // [2.5]
const res10 = await client.json.numIncrBy("crashes", "$", -0.75);
console.log(res10) // [1.75]
java
String res7 = jedis.jsonSet("crashes", new Path2("$"), 0);
System.out.println(res7); // >>> OK
Object res8 = jedis.jsonNumIncrBy("crashes", new Path2("$"), 1);
System.out.println(res8); // >>> [1]
Object res9 = jedis.jsonNumIncrBy("crashes", new Path2("$"), 1.5);
System.out.println(res9); // >>> [2.5]
Object res10 = jedis.jsonNumIncrBy("crashes", new Path2("$"), -0.75);
System.out.println(res10); // >>> [1.75]
go
res7, err := rdb.JSONSet(ctx, "crashes", "$", 0).Result()
if err != nil {
panic(err)
}
fmt.Println(res7) // >>> OK
res8, err := rdb.JSONNumIncrBy(ctx, "crashes", "$", 1).Result()
if err != nil {
panic(err)
}
fmt.Println(res8) // >>> [1]
res9, err := rdb.JSONNumIncrBy(ctx, "crashes", "$", 1.5).Result()
if err != nil {
panic(err)
}
fmt.Println(res9) // >>> [2.5]
res10, err := rdb.JSONNumIncrBy(ctx, "crashes", "$", -0.75).Result()
if err != nil {
panic(err)
}
fmt.Println(res10) // >>> [1.75]
csharp
bool res7 = db.JSON().Set("crashes", "$", 0);
Console.WriteLine(res7); // >>> True
double?[] res8 = db.JSON().NumIncrby("crashes", "$", 1);
Console.WriteLine(res8); // >>> 1
double?[] res9 = db.JSON().NumIncrby("crashes", "$", 1.5);
Console.WriteLine(res9); // >>> 2.5
double?[] res10 = db.JSON().NumIncrby("crashes", "$", -0.75);
Console.WriteLine(res9); // >>> 1.75
下面是一个更有趣的示例,其中包含 JSON 数组和对象:
bash
> JSON.SET newbike $ '["Deimos", {"crashes": 0}, null]'
OK
> JSON.GET newbike $
"[[\"Deimos\",{\"crashes\":0},null]]"
> JSON.GET newbike $[1].crashes
"[0]"
> JSON.DEL newbike $[-1]
(integer) 1
> JSON.GET newbike $
"[[\"Deimos\",{\"crashes\":0}]]"
python
res11 = r.json().set("newbike", "$", ["Deimos", {"crashes": 0}, None])
print(res11) # >>> True
res12 = r.json().get("newbike", "$")
print(res12) # >>> ['["Deimos", { "crashes": 0 }, null]']
res13 = r.json().get("newbike", "$[1].crashes")
print(res13) # >>> ['0']
res14 = r.json().delete("newbike", "$.[-1]")
print(res14) # >>> [1]
res15 = r.json().get("newbike", "$")
print(res15) # >>> [['Deimos', {'crashes': 0}]]
js
const res11 = await client.json.set("newbike", "$", ["Deimos", {"crashes": 0 }, null]);
console.log(res11); // OK
const res12 = await client.json.get("newbike", "$");
console.log(res12); // [ 'Deimos', { crashes: 0 }, null ]
const res13 = await client.json.get("newbike", "$[1].crashes");
console.log(res13); // [ 'Deimos', { crashes: 0 }, null ]
const res14 = await client.json.del("newbike", "$.[-1]");
console.log(res14); // [1]
const res15 = await client.json.get("newbike", "$");
console.log(res15); // [ 'Deimos', { crashes: 0 } ]
java
String res11 = jedis.jsonSet("newbike", new Path2("$"),
new JSONArray()
.put("Deimos")
.put(new JSONObject().put("crashes", 0))
.put((Object) null)
);
System.out.println(res11); // >>> OK
Object res12 = jedis.jsonGet("newbike", new Path2("$"));
System.out.println(res12); // >>> [["Deimos",{"crashes":0},null]]
Object res13 = jedis.jsonGet("newbike", new Path2("$[1].crashes"));
System.out.println(res13); // >>> [0]
long res14 = jedis.jsonDel("newbike", new Path2("$.[-1]"));
System.out.println(res14); // >>> 1
Object res15 = jedis.jsonGet("newbike", new Path2("$"));
System.out.println(res15); // >>> [["Deimos",{"crashes":0}]]
go
res11, err := rdb.JSONSet(ctx, "newbike", "$",
[]interface{}{
"Deimos",
map[string]interface{}{"crashes": 0},
nil,
},
).Result()
if err != nil {
panic(err)
}
fmt.Println(res11) // >>> OK
res12, err := rdb.JSONGet(ctx, "newbike", "$").Result()
if err != nil {
panic(err)
}
fmt.Println(res12) // >>> [["Deimos",{"crashes":0},null]]
res13, err := rdb.JSONGet(ctx, "newbike", "$[1].crashes").Result()
if err != nil {
panic(err)
}
fmt.Println(res13) // >>> [0]
res14, err := rdb.JSONDel(ctx, "newbike", "$.[-1]").Result()
if err != nil {
panic(err)
}
fmt.Println(res14) // >>> 1
res15, err := rdb.JSONGet(ctx, "newbike", "$").Result()
if err != nil {
panic(err)
}
fmt.Println(res15) // >>> [["Deimos",{"crashes":0}]]
csharp
bool res11 = db.JSON().Set("newbike", "$", new object?[] { "Deimos", new { crashes = 0 }, null });
Console.WriteLine(res11); // >>> True
RedisResult res12 = db.JSON().Get("newbike", path: "$");
Console.WriteLine(res12); // >>> [["Deimos",{"crashes":0},null]]
RedisResult res13 = db.JSON().Get("newbike", path: "$[1].crashes");
Console.WriteLine(res13); // >>> [0]
long res14 = db.JSON().Del("newbike", "$.[-1]");
Console.WriteLine(res14); // >>> 1
RedisResult res15 = db.JSON().Get("newbike", path: "$");
Console.WriteLine(res15); // >>> [["Deimos",{"crashes":0}]]
JSON.DEL
命令删除您使用path
参数指定的任何 JSON 值。
您可以使用专用的 JSON 命令子集操作数组:
bash
> JSON.SET riders $ []
OK
> JSON.ARRAPPEND riders $ '"Norem"'
1) (integer) 1
> JSON.GET riders $
"[[\"Norem\"]]"
> JSON.ARRINSERT riders $ 1 '"Prickett"' '"Royce"' '"Castilla"'
1) (integer) 4
> JSON.GET riders $
"[[\"Norem\",\"Prickett\",\"Royce\",\"Castilla\"]]"
> JSON.ARRTRIM riders $ 1 1
1) (integer) 1
> JSON.GET riders $
"[[\"Prickett\"]]"
> JSON.ARRPOP riders $
1) "\"Prickett\""
> JSON.ARRPOP riders $
1) (nil)
python
res16 = r.json().set("riders", "$", [])
print(res16) # >>> True
res17 = r.json().arrappend("riders", "$", "Norem")
print(res17) # >>> [1]
res18 = r.json().get("riders", "$")
print(res18) # >>> [['Norem']]
res19 = r.json().arrinsert("riders", "$", 1, "Prickett", "Royce", "Castilla")
print(res19) # >>> [4]
res20 = r.json().get("riders", "$")
print(res20) # >>> [['Norem', 'Prickett', 'Royce', 'Castilla']]
res21 = r.json().arrtrim("riders", "$", 1, 1)
print(res21) # >>> [1]
res22 = r.json().get("riders", "$")
print(res22) # >>> [['Prickett']]
res23 = r.json().arrpop("riders", "$")
print(res23) # >>> ['"Prickett"']
res24 = r.json().arrpop("riders", "$")
print(res24) # >>> [None]
js
const res16 = await client.json.set("riders", "$", []);
console.log(res16); // OK
const res17 = await client.json.arrAppend("riders", "$", "Norem");
console.log(res17); // [1]
const res18 = await client.json.get("riders", "$");
console.log(res18); // [ 'Norem' ]
const res19 = await client.json.arrInsert("riders", "$", 1, "Prickett", "Royse", "Castilla");
console.log(res19); // [4]
const res20 = await client.json.get("riders", "$");
console.log(res20); // [ 'Norem', 'Prickett', 'Royse', 'Castilla' ]
const res21 = await client.json.arrTrim("riders", "$", 1, 1);
console.log(res21); // [1]
const res22 = await client.json.get("riders", "$");
console.log(res22); // [ 'Prickett' ]
const res23 = await client.json.arrPop("riders", "$");
console.log(res23); // [ 'Prickett' ]
const res24 = await client.json.arrPop("riders", "$");
console.log(res24); // [null]
java
String res16 = jedis.jsonSet("riders", new Path2("$"), new JSONArray());
System.out.println(res16); // >>> OK
List<Long> res17 = jedis.jsonArrAppendWithEscape("riders", new Path2("$"), "Norem");
System.out.println(res17); // >>> [1]
Object res18 = jedis.jsonGet("riders", new Path2("$"));
System.out.println(res18); // >>> [["Norem"]]
List<Long> res19 = jedis.jsonArrInsertWithEscape(
"riders", new Path2("$"), 1, "Prickett", "Royce", "Castilla"
);
System.out.println(res19); // >>> [4]
Object res20 = jedis.jsonGet("riders", new Path2("$"));
System.out.println(res20);
// >>> [["Norem","Prickett","Royce","Castilla"]]
List<Long> res21 = jedis.jsonArrTrim("riders", new Path2("$"), 1, 1);
System.out.println(res21); // >>> [1]
Object res22 = jedis.jsonGet("riders", new Path2("$"));
System.out.println(res22); // >>> [["Prickett"]]
Object res23 = jedis.jsonArrPop("riders", new Path2("$"));
System.out.println(res23); // >>> [Prickett]
Object res24 = jedis.jsonArrPop("riders", new Path2("$"));
System.out.println(res24); // >>> [null]
go
res16, err := rdb.JSONSet(ctx, "riders", "$", []interface{}{}).Result()
if err != nil {
panic(err)
}
fmt.Println(res16) // >>> OK
res17, err := rdb.JSONArrAppend(ctx, "riders", "$", "\"Norem\"").Result()
if err != nil {
panic(err)
}
fmt.Println(res17) // >>> [1]
res18, err := rdb.JSONGet(ctx, "riders", "$").Result()
if err != nil {
panic(err)
}
fmt.Println(res18) // >>> [["Norem"]]
res19, err := rdb.JSONArrInsert(ctx, "riders", "$", 1,
"\"Prickett\"", "\"Royce\"", "\"Castilla\"",
).Result()
if err != nil {
panic(err)
}
fmt.Println(res19) // [3]
res20, err := rdb.JSONGet(ctx, "riders", "$").Result()
if err != nil {
panic(err)
}
fmt.Println(res20) // >>> [["Norem", "Prickett", "Royce", "Castilla"]]
rangeStop := 1
res21, err := rdb.JSONArrTrimWithArgs(ctx, "riders", "$",
&redis.JSONArrTrimArgs{Start: 1, Stop: &rangeStop},
).Result()
if err != nil {
panic(err)
}
fmt.Println(res21) // >>> [1]
res22, err := rdb.JSONGet(ctx, "riders", "$").Result()
if err != nil {
panic(err)
}
fmt.Println(res22) // >>> [["Prickett"]]
res23, err := rdb.JSONArrPop(ctx, "riders", "$", -1).Result()
if err != nil {
panic(err)
}
fmt.Println(res23) // >>> [["Prickett"]]
res24, err := rdb.JSONArrPop(ctx, "riders", "$", -1).Result()
if err != nil {
panic(err)
}
fmt.Println(res24) // []
csharp
bool res16 = db.JSON().Set("riders", "$", new object[] { });
Console.WriteLine(res16); // >>> True
long?[] res17 = db.JSON().ArrAppend("riders", "$", "Norem");
Console.WriteLine(string.Join(", ", res17)); // >>> 1
RedisResult res18 = db.JSON().Get("riders", path: "$");
Console.WriteLine(res18); // >>> [["Norem"]]
long?[] res19 = db.JSON().ArrInsert("riders", "$", 1, "Prickett", "Royce", "Castilla");
Console.WriteLine(string.Join(", ", res19)); // >>> 4
RedisResult res20 = db.JSON().Get("riders", path: "$");
Console.WriteLine(res20); // >>> [["Norem","Prickett","Royce","Castilla"]]
long?[] res21 = db.JSON().ArrTrim("riders", "$", 1, 1);
Console.WriteLine(string.Join(", ", res21)); // 1
RedisResult res22 = db.JSON().Get("riders", path: "$");
Console.WriteLine(res22); // >>> [["Prickett"]]
RedisResult[] res23 = db.JSON().ArrPop("riders", "$");
Console.WriteLine(string.Join(", ", (object[])res23)); // >>> "Prickett"
RedisResult[] res24 = db.JSON().ArrPop("riders", "$");
Console.WriteLine(string.Join(", ", (object[])res24)); // >>> <Empty string>
JSON 对象也有自己的命令:
bash
> JSON.SET bike:1 $ '{"model": "Deimos", "brand": "Ergonom", "price": 4972}'
OK
> JSON.OBJLEN bike:1 $
1) (integer) 3
> JSON.OBJKEYS bike:1 $
1) 1) "model"
2) "brand"
3) "price"
python
res25 = r.json().set(
"bike:1", "$", {"model": "Deimos", "brand": "Ergonom", "price": 4972}
)
print(res25) # >>> True
res26 = r.json().objlen("bike:1", "$")
print(res26) # >>> [3]
res27 = r.json().objkeys("bike:1", "$")
print(res27) # >>> [['model', 'brand', 'price']]
js
const res25 = await client.json.set(
"bike:1", "$", {
"model": "Deimos",
"brand": "Ergonom",
"price": 4972
}
);
console.log(res25); // OK
const res26 = await client.json.objLen("bike:1", "$");
console.log(res26); // [3]
const res27 = await client.json.objKeys("bike:1", "$");
console.log(res27); // [['model', 'brand', 'price']]
java
String res25 = jedis.jsonSet("bike:1", new Path2("$"),
new JSONObject()
.put("model", "Deimos")
.put("brand", "Ergonom")
.put("price", 4972)
);
System.out.println(res25); // >>> OK
List<Long> res26 = jedis.jsonObjLen("bike:1", new Path2("$"));
System.out.println(res26); // >>> [3]
List<List<String>> res27 = jedis.jsonObjKeys("bike:1", new Path2("$"));
System.out.println(res27); // >>> [[price, model, brand]]
go
res25, err := rdb.JSONSet(ctx, "bike:1", "$",
map[string]interface{}{
"model": "Deimos",
"brand": "Ergonom",
"price": 4972,
},
).Result()
if err != nil {
panic(err)
}
fmt.Println(res25) // >>> OK
res26, err := rdb.JSONObjLen(ctx, "bike:1", "$").Result()
if err != nil {
panic(err)
}
fmt.Println(*res26[0]) // >>> 3
res27, err := rdb.JSONObjKeys(ctx, "bike:1", "$").Result()
if err != nil {
panic(err)
}
fmt.Println(res27) // >>> [brand model price]
csharp
bool res25 = db.JSON().Set("bike:1", "$",
new { model = "Deimos", brand = "Ergonom", price = 4972 }
);
Console.WriteLine(res25); // >>> True
long?[] res26 = db.JSON().ObjLen("bike:1", "$");
Console.WriteLine(string.Join(", ", res26)); // >>> 3
IEnumerable<HashSet<string>> res27 = db.JSON().ObjKeys("bike:1", "$");
Console.WriteLine(
string.Join(", ", res27.Select(b => $"{string.Join(", ", b.Select(c => $"{c}"))}"))
); // >>> model, brand, price
格式化 CLI 输出
CLI 具有原始输出模式,允许您从JSON.GET
向输出添加格式,使它更具可读性。要使用此选项,请使用redis-cli
和选项--raw
, 使用JSON.GET
并包括格式关键字比如:INDENT
, NEWLINE
, 和 SPACE
bash
$ redis-cli --raw
> JSON.GET obj INDENT "\t" NEWLINE "\n" SPACE " " $
[
{
"name": "Leonard Cohen",
"lastSeen": 1478476800,
"loggedOut": true
}
]
启用 Redis JSON
默认情况下,Redis JSON 在基本 Redis 服务器中不可用,因此您 应该安装 Redis Stack 或 Redis Enterprise, 这两个模块都包括 JSON 和其他有用的模块。 有关完整的安装说明,请参阅安装 Redis 堆栈或安装 Redis Enterprise。
限度
传递给命令的 JSON 值的最大深度为 128。如果向命令传递一个 JSON 值,该值包含嵌套级别超过 128 的对象或数组,则该命令将返回错误。
更多信息
阅读本节中的其他页面,了解有关 Redis JSON 的更多信息
索引/搜索 JSON 文档
将 Redis JSON 和 Redis 查询引擎相结合,以索引和搜索 JSON 文档
路径
访问 JSON 文档中的特定元素
使用案例
JSON 使用案例
性能
性能基准
Redis JSON RAM 使用情况
调试内存消耗
从 RESP2 迁移到 RESP3 回复的指南
面向客户端开发人员的 JSON RESP2 到 RESP3 回复参考
开发人员说明
有关 JSON 调试、测试和文档的说明。