【Redis精通之路】数据类型(2)

目录

[1 Strings](#1 Strings)

[1.1 字符串作为计数器](#1.1 字符串作为计数器)

[1.2 限制](#1.2 限制)

[1.3 按位运算](#1.3 按位运算)

[1.4 性能](#1.4 性能)

[1.5 其他方案](#1.5 其他方案)

[2 JSON](#2 JSON)

[2.1 主要功能](#2.1 主要功能)

[2.2 使用方法](#2.2 使用方法)

[2.3 格式化CLI输出](#2.3 格式化CLI输出)

[2.4 启动Redis](#2.4 启动Redis)

[2.4.1 Docker](#2.4.1 Docker)

[2.4.2 二进制文件](#2.4.2 二进制文件)

[2.4.3 源代码构建](#2.4.3 源代码构建)

[2.4.4 将模块加载到Redis](#2.4.4 将模块加载到Redis)

[2.5 限制](#2.5 限制)

[2.6 索引](#2.6 索引)

[2.7 Path](#2.7 Path)

[2.7.1 JSONPath支持](#2.7.1 JSONPath支持)

[2.7.2 JSONPath语法](#2.7.2 JSONPath语法)

[2.7.3 JSONPath示例](#2.7.3 JSONPath示例)

[2.7.4 查询示例](#2.7.4 查询示例)

[2.7.5 过滤示例](#2.7.5 过滤示例)

[2.7.6 修改示例](#2.7.6 修改示例)

[2.7.7 传统匹配语法](#2.7.7 传统匹配语法)

[2.7.8 兼容性](#2.7.8 兼容性)

[2.7.9 时间复杂度](#2.7.9 时间复杂度)

[2.8 用例](#2.8 用例)

[2.9 性能](#2.9 性能)

[3 Lists](#3 Lists)

[4 Sets](#4 Sets)

[5 Hashes](#5 Hashes)

[6 Sorted sets](#6 Sorted sets)

[7 Streams](#7 Streams)

[8 Geospatial](#8 Geospatial)

[9 Bitmaps](#9 Bitmaps)

[10 Bitfields](#10 Bitfields)

[11 Probabilistic](#11 Probabilistic)

[12 Time series](#12 Time series)


Redis支持的数据类型概述

Redis是一个数据结构服务器。Redis的核心是提供一组本地数据类型,帮助您解决从缓存排队 再到事件处理等各种问题。

Redis支持几种数据类型?

你肯定回答不对。

因为在我没详读官网的时候,没想到有这么多。

Redis目前一共支持12种数据类型(99%的朋友一定还认为时5种,或7种)

欢迎大家点赞,关注,收藏,一键三连~

让我们娓娓道来,Redis各个数据类型的功能和特点,结构和原理。

1 Strings

Redis字符串是最基本的Redis数据类型,表示一个字节数组

**Redis字符串存储字节数组,**包括文本、序列化对象和二进制数组。因此,字符串是可以与Redis的key关联的最简单的值类型。它们通常用于缓存,但它们支持额外的功能,允许您实现计数器并执行逐位操作。

由于Redis键是字符串,当我们也使用字符串类型作为值时,我们将一个字符串映射到另一个字符串。字符串数据类型对许多用例都很有用,比如缓存HTML片段或页面。

bash 复制代码
    > SET bike:1 Deimos
    OK
    > GET bike:1
    "Deimos"

正如您所看到的,使用SETGET命令是我们设置和检索字符串值的方式。

请注意,在密钥已经存在的情况下,SET将替换已经存储在密钥中的任何现有值,即使该key与非字符串值相关联。

值可以是各种字符串(包括二进制数据),例如,您可以在值中存储jpeg图像。值不能大于512 MB。

SET命令有一些有趣的选项,这些选项作为附加参数提供。

例如,如果密钥已经存在,我可能会要求SET失败,或者相反,只有当密钥已经存在时,它才能成功:

bash 复制代码
    > set bike:1 bike nx
    (nil)
    > set bike:1 bike xx
    OK

博主PS:setnx常用于分布式锁的使用。

还有许多其他用于对字符串进行操作的命令。例如,GETSET命令将键设置为新值,并返回旧值作为结果。

例如,如果您有一个系统,每当您的网站接收到新访问者时,都会使用INCR递增Redis密钥,则可以使用此命令。

您可能希望每小时收集一次此信息,而不会丢失一个增量。您可以设置密钥,为其分配新值"0"并读取旧值。

在单个命令中设置或检索多个键的值的能力对于减少延迟也很有用

博主PS:因为如果get后再set两条命令的执行可能会有延迟

由于这个原因,存在MSET和MGET命令:

bash 复制代码
    > mset bike:1 "Deimos" bike:2 "Ares" bike:3 "Vanth"
    OK
    > mget bike:1 bike:2 bike:3
    1) "Deimos"
    2) "Ares"
    3) "Vanth"

当使用MGET时,Redis返回一个值数组。

1.1 字符串作为计数器

即使字符串是Redis的基本值,也可以使用它们执行一些有趣的操作。例如,一种是原子增量:

INCR命令将字符串值解析为整数,然后将其递增一,最后将获得的值设置为新值。还有其他类似的命令,如INCRBYDECRDECRBY。在内部,它常常是类似的命令,以稍微不同的方式执行。

INCR是原子的 ,这意味着什么?即使多个客户端针对同一密钥发出INCR,也永远不会进入竞争状态。例如,永远不会发生客户端1读取"10",客户端2同时读取"10",两者都递增到11,并将新值设置为11。最终值将始终为12,并且在所有其他客户端不同时执行命令时执行读取增量设置操作。

博主PS:因为提交给redis执行的命令,redis会以串行的方式执行,所以每个命令都是原子性的。

1.2 限制

默认情况下,单个Redis字符串的最大容量为512 MB。

1.3 按位运算

要对字符串执行逐位操作,请参阅Bitmap数据类型文档。

请参阅字符串命令的完整列表。

1.4 性能

大多数字符串操作都是O(1),这意味着它们非常高效。

但是,要小心SUBSTR、GETRANGESETRANGE 命令,它们可以是O(n)

在处理大型字符串时,这些随机访问字符串命令可能会导致性能问题。

1.5 其他方案

如果您将结构化数据存储为序列化字符串 ,您可能还需要了解其他Redis结构**, HASH** 或JSON

2 JSON

bash 复制代码
> JSON.SET bike $ '"Hyperion"'
OK
> JSON.GET bike $
"[\"Hyperion\"]"
> JSON.TYPE bike $
1) "string"

Redis Stack的JSON功能为Redis提供了JavaScript Object Notation(JSON)支持。它允许您在Redis数据库中存储、更新和检索JSON值,类似于任何其他Redis数据类型。Redis JSON还可以与搜索和查询无缝配合,使您可以索引和查询JSON文档。

2.1 主要功能

完全支持JSON标准

用于选择/更新文档内部元素的JSONPath语法(请参阅JSONPath句法)

以二进制数据形式存储在树结构中的文档,允许快速访问子元素

所有JSON值类型的类型化原子操作

2.2 使用方法

​要尝试的第一个JSON命令是JSON.SET,它设置了一个值为JSON值的KEY。JSON.SET接受所有JSON值类型。此示例创建一个JSON字符串:

bash 复制代码
> JSON.SET bike $ '"Hyperion"'
OK
> JSON.GET bike $
"[\"Hyperion\"]"
> JSON.TYPE bike $
1) "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)\"]"

数字可以递增和相乘:

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]"

下面是一个更有趣的示例,其中包括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}]]"

JSON.DEL命令将删除您指定的任何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)

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"

2.3 格式化CLI输出

CLI具有原始输出模式,可以为JSON的输出添加格式。获取以使其可读性更强。要使用它,请使用**--raw选项运行redis-cli**,并使用JSON包含格式关键字,如INDENTNEWLINESPACE(缩进,换行,空格)

bash 复制代码
$ redis-cli --raw
> JSON.GET obj INDENT "\t" NEWLINE "\n" SPACE " " $
[
	{
		"name": "Leonard Cohen",
		"lastSeen": 1478476800,
		"loggedOut": true
	}
]

Redis JSON 被实现为一个扩展Redis基本服务器的模块。Redis Stack和Redis Enterprise默认包含此模块,但如果它不可用,您也可以动态加载它。

2.4 启动Redis

下面介绍了访问Redis JSON的不同方式。

2.4.1 Docker

要使用Docker运行RedisJSON,请使用redis stack服务器Docker镜像:

$ docker run -d --name redis-stack-server -p 6379:6379 redis/redis-stack-server:latest

有关在Docker容器中运行Redis Stack的更多信息,请参阅在Docker上运行Redis stack。

2.4.2 二进制文件

要下载并运行Redis JSON 插件,该模块从预编译的二进制文件中提供JSON数据结构:

从Redis下载中心下载预编译版本。Downloads - Redis

将插件加载到Redis中

$ redis-server --loadmodule /path/to/module/src/rejson.so
2.4.3 源代码构建

要从源代码构建RedisJSON,请执行以下操作:

克隆github仓库(确保包含**--recursive选项**以正确克隆子模块):

$ git clone --recursive https://github.com/RedisJSON/RedisJSON.git
$ cd RedisJSON

安装依赖项:

$ ./sbin/setup

构建

$ make build
2.4.4 将模块加载到Redis

要求:

一般来说,最好运行最新版本的Redis。

如果您的操作系统有Redis 6.x或更高版本的软件包,您可以使用操作系统软件包管理器进行安装。

否则,您可以调用

$ ./deps/readies/bin/getredis

要加载Redis JSON模块,请使用以下方法之一:

1.Makefile配方

使用RedisJSON运行Redis:

$ make run

2.配置文件:

或者,您可以在启动时将以下内容添加到Redis.conf文件中,让Redis加载模块:

loadmodule /path/to/module/target/release/librejson.so

在Mac OS上,如果此模块是作为动态库构建的,请运行:

loadmodule /path/to/module/target/release/librejson.dylib

在上面的行中,将/path/to/module/替换为模块的实际路径。

3.命令行选项

您也可以让Redis使用以下命令行参数语法加载模块:

$ redis-server --loadmodule /path/to/module/librejson.so

在上面的行中,将/path/to/module/替换为模块库的实际路径。

4.MODULE LOAD命令

您也可以使用MODULE LOAD命令来加载Redis JSON。请注意,MODULE LOAD是一个危险的命令,出于安全考虑,将来可能会被阻止/弃用。

成功加载模块后,Redis日志中的行应类似于:

...
9:M 11 Aug 2022 16:24:06.701 * <ReJSON> version: 20009 git sha: d8d4b19 branch: HEAD
9:M 11 Aug 2022 16:24:06.701 * <ReJSON> Exported RedisJSON_V1 API
9:M 11 Aug 2022 16:24:06.701 * <ReJSON> Enabled diskless replication
9:M 11 Aug 2022 16:24:06.701 * <ReJSON> Created new data type 'ReJSON-RL'
9:M 11 Aug 2022 16:24:06.701 * Module 'ReJSON' loaded from /opt/redis-stack/lib/rejson.so
...

2.5 限制

传递给命令的JSON值的深度可以高达128。如果向命令传递JSON值,该值包含嵌套级别超过128的对象或数组,则该命令将返回错误。

2.6 索引

将Redis JSON与Search and Query相结合,对JSON文档进行索引搜索

除了存储JSON文档,您还可以使用搜索和查询功能对它们进行索引。这实现了全文搜索功能基于内容的文档检索。

要使用这些功能,您必须安装两个模块:RedisJSONRediSearchRedis Stack自动包含这两个模块。

请参阅教程,了解如何搜索和查询JSON。

2.7 Path

访问JSON文档中的特定元素

Path 允许您访问JSON文档中的特定元素。由于没有JSONPath 语法的标准,Redis JSON实现了自己的Path 语法。JSON的语法基于常见的最佳实践,有意与JSONPath相似。

JSON支持两种查询语法:JSONPath语法和JSON第一个版本的传统路径语法。

JSON根据路径查询的第一个字符知道要使用哪种语法。如果查询以字符$开头,则使用JSONPath语法。否则,它将默认为传统路径语法。

返回的值是一个JSON字符串,其中包含JSON序列化字符串的顶级数组。如果使用多路径,则返回值是一个JSON字符串,其中包含一个顶级对象,该对象的值是序列化JSON值的数组。

2.7.1 JSONPath支持

RedisJSON v2.0引入了对JSONPath 的支持。它遵循Goessner在文章中描述的语法。

JSONPath查询可以解析到JSON文档中的多个位置。

在这种情况下,JSON命令将操作应用于每个可能的位置。这是对仅在第一条路径上操作的传统路径查询的一个重大改进。

请注意,当使用JSONPath时,命令响应的结构通常会有所不同。有关详细信息,请参阅"命令"页面。

新语法支持括号表示法,允许在键名中使用冒号":"或空格等特殊字符。

如果要在CLI的查询中包含双引号,请将JSONPath括在单引号内。例如

JSON.GET store '$.inventory["mountain_bikes"]'
2.7.2 JSONPath语法

以下JSONPath语法表改编自Goessner的路径语法比较。

语法符号 描述
$ 根(最外层的JSON元素)启动路径。
. or [] 选择一个子元素。
.. 递归地遍历JSON文档。
* 通配符,返回所有元素。
[] 下标运算符,访问数组元素。
[,] 并集,选择多个元素。
[start:end:step] 数组切片,其中开始、结束和步长是索引。
?() 过滤JSON对象或数组。支持比较运算符(==,!=,<,<=,>,>=,=~)、逻辑运算符(&&,||)和括号((,))。
() 脚本表达式。
@ 当前元素,用于筛选器或脚本表达式。
2.7.3 JSONPath示例

以下JSONPath示例使用此JSON文档,该文档存储了商店库存中项目的详细信息:

javascript 复制代码
{
    "inventory": {
        "mountain_bikes": [
            {
                "id": "bike:1",
                "model": "Phoebe",
                "description": "This is a mid-travel trail slayer that is a fantastic daily driver or one bike quiver. The Shimano Claris 8-speed groupset gives plenty of gear range to tackle hills and there\u2019s room for mudguards and a rack too.  This is the bike for the rider who wants trail manners with low fuss ownership.",
                "price": 1920,
                "specs": {"material": "carbon", "weight": 13.1},
                "colors": ["black", "silver"],
            },
            {
                "id": "bike:2",
                "model": "Quaoar",
                "description": "Redesigned for the 2020 model year, this bike impressed our testers and is the best all-around trail bike we've ever tested. The Shimano gear system effectively does away with an external cassette, so is super low maintenance in terms of wear and tear. All in all it's an impressive package for the price, making it very competitive.",
                "price": 2072,
                "specs": {"material": "aluminium", "weight": 7.9},
                "colors": ["black", "white"],
            },
            {
                "id": "bike:3",
                "model": "Weywot",
                "description": "This bike gives kids aged six years and older a durable and uberlight mountain bike for their first experience on tracks and easy cruising through forests and fields. A set of powerful Shimano hydraulic disc brakes provide ample stopping ability. If you're after a budget option, this is one of the best bikes you could get.",
                "price": 3264,
                "specs": {"material": "alloy", "weight": 13.8},
            },
        ],
        "commuter_bikes": [
            {
                "id": "bike:4",
                "model": "Salacia",
                "description": "This bike is a great option for anyone who just wants a bike to get about on With a slick-shifting Claris gears from Shimano\u2019s, this is a bike which doesn\u2019t break the bank and delivers craved performance.  It\u2019s for the rider who wants both efficiency and capability.",
                "price": 1475,
                "specs": {"material": "aluminium", "weight": 16.6},
                "colors": ["black", "silver"],
            },
            {
                "id": "bike:5",
                "model": "Mimas",
                "description": "A real joy to ride, this bike got very high scores in last years Bike of the year report. The carefully crafted 50-34 tooth chainset and 11-32 tooth cassette give an easy-on-the-legs bottom gear for climbing, and the high-quality Vittoria Zaffiro tires give balance and grip.It includes a low-step frame , our memory foam seat, bump-resistant shocks and conveniently placed thumb throttle. Put it all together and you get a bike that helps redefine what can be done for this price.",
                "price": 3941,
                "specs": {"material": "alloy", "weight": 11.6},
            },
        ],
    }
}

首先,在数据库中创建JSON文档:

bash 复制代码
JSON.SET bikes:inventory $ '{ "inventory": { "mountain_bikes": [ { "id": "bike:1", "model": "Phoebe", "description": "This is a mid-travel trail slayer that is a fantastic daily driver or one bike quiver. The Shimano Claris 8-speed groupset gives plenty of gear range to tackle hills and there\'s room for mudguards and a rack too. This is the bike for the rider who wants trail manners with low fuss ownership.", "price": 1920, "specs": {"material": "carbon", "weight": 13.1}, "colors": ["black", "silver"] }, { "id": "bike:2", "model": "Quaoar", "description": "Redesigned for the 2020 model year, this bike impressed our testers and is the best all-around trail bike we\'ve ever tested. The Shimano gear system effectively does away with an external cassette, so is super low maintenance in terms of wear and tear. All in all it\'s an impressive package for the price, making it very competitive.", "price": 2072, "specs": {"material": "aluminium", "weight": 7.9}, "colors": ["black", "white"] }, { "id": "bike:3", "model": "Weywot", "description": "This bike gives kids aged six years and older a durable and uberlight mountain bike for their first experience on tracks and easy cruising through forests and fields. A set of powerful Shimano hydraulic disc brakes provide ample stopping ability. If you\'re after a budget option, this is one of the best bikes you could get.", "price": 3264, "specs": {"material": "alloy", "weight": 13.8} } ], "commuter_bikes": [ { "id": "bike:4", "model": "Salacia", "description": "This bike is a great option for anyone who just wants a bike to get about on With a slick-shifting Claris gears from Shimano\'s, this is a bike which doesn\'t break the bank and delivers craved performance. It\'s for the rider who wants both efficiency and capability.", "price": 1475, "specs": {"material": "aluminium", "weight": 16.6}, "colors": ["black", "silver"] }, { "id": "bike:5", "model": "Mimas", "description": "A real joy to ride, this bike got very high scores in last years Bike of the year report. The carefully crafted 50-34 tooth chainset and 11-32 tooth cassette give an easy-on-the-legs bottom gear for climbing, and the high-quality Vittoria Zaffiro tires give balance and grip.It includes a low-step frame , our memory foam seat, bump-resistant shocks and conveniently placed thumb throttle. Put it all together and you get a bike that helps redefine what can be done for this price.", "price": 3941, "specs": {"material": "alloy", "weight": 11.6} } ] }}'
2.7.4 查询示例

以下示例使用JSON.GET命令从JSON文档中的各种路径检索数据。

您可以使用通配符运算符*返回库存中所有项目的列表:

bash 复制代码
JSON.GET bikes:inventory $.inventory.*
"[[{\"id\":\"bike:1\",\"model\":\"Phoebe\",\"description\":\"This is a mid-travel trail slayer...

对于某些查询,多个路径可以产生相同的结果。例如,以下路径返回所有山地自行车的名称:

bash 复制代码
> JSON.GET bikes:inventory $.inventory.mountain_bikes[*].model
"[\"Phoebe\",\"Quaoar\",\"Weywot\"]"
> JSON.GET bikes:inventory '$.inventory["mountain_bikes"][*].model'
"[\"Phoebe\",\"Quaoar\",\"Weywot\"]"
> JSON.GET bikes:inventory '$..mountain_bikes[*].model'
"[\"Phoebe\",\"Quaoar\",\"Weywot\"]"

递归下降运算符。。可以从JSON文档的多个部分检索字段。以下示例返回所有库存项的名称:

bash 复制代码
> JSON.GET bikes:inventory $..model
"[\"Phoebe\",\"Quaoar\",\"Weywot\",\"Salacia\",\"Mimas\"]"

可以使用阵列切片从阵列中选择一系列元素。此示例返回前2辆山地自行车的名称:

bash 复制代码
> JSON.GET bikes:inventory $..mountain_bikes[0:2].model
"[\"Phoebe\",\"Quaoar\"]"

筛选表达式?()允许您根据特定条件选择JSON元素。

您可以在这些表达式中使用比较运算符(==,!=,<,<=,>,>=,从v2.4.2版本开始,也可以使用=~)、逻辑运算符(&&,||)和括号((,))。

筛选表达式可以应用于数组或对象,迭代数组中的所有元素或对象中的所有值,只检索与筛选条件匹配的值。

筛选条件中的路径使用点表示法,其中@表示当前数组元素或当前对象值,$表示顶级元素。

例如,使用@.key_name引用嵌套值,使用$.top_level_key_name引用顶级值。

从v2.4.2版本起,您可以使用比较运算符=~将左侧的字符串值的路径与右侧的正则表达式模式进行匹配。

有关更多信息,请参阅支持的正则表达式语法文档。

非字符串值不匹配。只有当左侧是字符串值的路径,而右侧是硬编码字符串或字符串值的道路时,才能发生匹配。请参阅以下示例。

正则表达式匹配是部分的,这意味着像"foo"这样的正则表达式模式匹配像"barefoots"这样的字符串。要使匹配精确,请使用正则表达式模式"^foo$"。

其他JSONPath引擎 可能在**斜杠之间使用正则表达式模式(例如/foo/),**并且它们的匹配是精确的。

它们可以使用正则表达式模式(如/.*foo.*/)执行部分匹配。

2.7.5 过滤示例

在以下示例中,过滤仅返回价格低于3000且重量低于10的山地自行车:

bash 复制代码
> JSON.GET bikes:inventory '$..mountain_bikes[?(@.price < 3000 && @.specs.weight < 10)]'
"[{\"id\":\"bike:2\",\"model\":\"Quaoar\",\"description\":\"Redesigned for the 2020 model year...

此示例过滤合金自行车型号名称的库存:

bash 复制代码
> JSON.GET bikes:inventory '$..[?(@.specs.material == "alloy")].model'
"[\"Weywot\",\"Mimas\"]"

此示例从v2.4.2版本起有效,仅过滤以"al-"开头的自行车。

请注意,由于正则表达式模式**"(?i)al"** 中的前缀**(?i),匹配时不区分大小写**

bash 复制代码
JSON.GET bikes:inventory '$..[?(@.specs.material =~ "(?i)al")].model'
"[\"Quaoar\",\"Weywot\",\"Salacia\",\"Mimas\"]"

您还可以使用JSON对象本身的属性指定正则表达式模式

例如,如前一个示例所示,我们可以向每辆山地自行车添加一个名为regex_pat的字符串属性,其值为**"(?i)al"**以匹配数据,然后,我们可以将regex_pat与自行车进行匹配:

bash 复制代码
> JSON.SET bikes:inventory $.inventory.mountain_bikes[0].regex_pat '"(?i)al"'
OK
> JSON.SET bikes:inventory $.inventory.mountain_bikes[1].regex_pat '"(?i)al"'
OK
> JSON.SET bikes:inventory $.inventory.mountain_bikes[2].regex_pat '"(?i)al"'
OK
> JSON.GET bikes:inventory '$.inventory.mountain_bikes[?(@.specs.material =~ @.regex_pat)].model'
"[\"Quaoar\",\"Weywot\"]"
2.7.6 修改示例

当您想要更新JSON文档的特定部分时,也可以使用JSONPath查询。

例如,您可以将JSONPath传递给JSON。SET命令更新特定字段。此示例更改耳机列表中第一个项目的价格:

bash 复制代码
> JSON.GET bikes:inventory $..price
"[1920,2072,3264,1475,3941]"
> JSON.NUMINCRBY bikes:inventory $..price -100
"[1820,1972,3164,1375,3841]"
> JSON.NUMINCRBY bikes:inventory $..price 100
"[1920,2072,3264,1475,3941]"

您可以使用过滤器表达式仅更新符合特定条件的JSON元素。

以下示例将任何自行车的价格设置为1500,如果其价格已经低于2000:

bash 复制代码
> JSON.SET bikes:inventory '$.inventory.*[?(@.price<2000)].price' 1500
OK
> JSON.GET bikes:inventory $..price
"[1500,2072,3264,1500,3941]"

JSONPath查询还可以与其他输入的路径作为参数的JSON命令一起使用。例如,您可以使用JSON为一组耳机添加一个新的颜色选项:

bash 复制代码
> JSON.ARRAPPEND bikes:inventory '$.inventory.*[?(@.price<2000)].colors' '"pink"'
1) (integer) 3
2) (integer) 3
127.0.0.1:6379> JSON.GET bikes:inventory $..[*].colors
"[[\"black\",\"silver\",\"pink\"],[\"black\",\"white\"],[\"black\",\"silver\",\"pink\"]]"
2.7.7 传统匹配语法

RedisJSON v1具有以下Path实现。除了JSONPath之外,JSON v2仍然支持这个传统Path。

Path总是从Redis JSON值的根开始。根由句点字符(.)表示。对于引用根的子级的Path,可以选择在Path前面加上根。

Redis JSON支持点表示法括号表示法用于对象key访问。以下Path指的是耳机,它是根目录下的子目录:

.inventory.headphones

inventory["headphones"]

['inventory']["headphones"]

要访问数组元素,请将其索引括在一对方括号内。索引是基于0的,0是数组的第一个元素,1是下一个元素,依此类推。您可以使用负偏移量来访问从数组末尾开始的元素。例如,-1是数组中的最后一个元素,-2是倒数第二个元素,依此类推。

2.7.8 兼容性

根据定义,JSON键可以是任何有效的JSON字符串。另一方面,Path传统上基于JavaScript(和Java)的变量命名约定。

尽管JSON可以存储包含任意密钥名称的对象,但只有在这些键符合以下命名语法规则的情况下,才能使用传统Path来访问这些键:

名称必须以字母美元符号($)下划线(_)字符开头

名称可以包含字母数字美元符号下划线

名称区分大小写

2.7.9 时间复杂度

搜索(导航到)Path中某个元素的时间复杂度计算如下:

子级别:路径上的每个级别都会增加一次搜索

关键字搜索:O(N) ,其中N是父对象中关键字的数量

数组搜索:O(1)

这意味着搜索路径的总体时间复杂度为O(N*M),其中N是深度,M是父对象键的数量。

虽然这对于N较小的对象是可以接受的,但对于较大的对象可以优化访问。

2.8 用例

当然,您可以使用Redis原生数据结构 来存储JSON对象**,这是一种常见的做法**。

例如,您可以序列化JSON并将其保存在Redis字符串中。

然而,Redis JSON提供了优于此方法的几个好处。

2.8.1 子值的访问和检索

使用JSON,您可以获得嵌套 的值,而无需通过网络传输整个对象。 当您在Redis中存储大型JSON对象时,访问子对象可以提高效率。

2.8.2 原子部分更新

JSON允许您以原子方式运行操作 ,如增加值添加删除数组中的元素、附加字符串等。

要对序列化对象执行同样的操作,您必须检索并保留整个对象,这可能很昂贵,也缺乏原子性。

2.8.3 索引和查询

当您将JSON对象存储为Redis字符串时,没有很好的方法来查询这些对象。

另一方面,使用Redis Stack将这些对象存储为JSON可以对它们进行索引查询。这是由Redis Stack的搜索和查询功能提供的。

2.9 性能

为了尽早了解Redis JSON的功能,您可以像其他Redis命令一样,使用Redis基准测试 测试它。然而,为了更好地控制测试,我们将使用Go中编写的一个名为ReJSONBenchmark的工具,我们预计该工具将在不久的将来发布。

下图包含了从AWS EC2 c4.8xlarge实例中获得Redis服务器基准测试工具

注意:

下面的结果是使用Redis JSON 的预览版本测试的,该版本仍然没有经过优化

未完待续......


3 Lists

4 Sets

5 Hashes

6 Sorted sets

7 Streams

8 Geospatial

9 Bitmaps

10 Bitfields

11 Probabilistic

12 Time series

相关推荐
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭9 分钟前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
工业甲酰苯胺9 分钟前
分布式系统架构:服务容错
数据库·架构
菜鸡中的奋斗鸡→挣扎鸡1 小时前
滑动窗口 + 算法复习
数据结构·算法
独行soc1 小时前
#渗透测试#漏洞挖掘#红蓝攻防#护网#sql注入介绍08-基于时间延迟的SQL注入(Time-Based SQL Injection)
数据库·sql·安全·渗透测试·漏洞挖掘
White_Mountain1 小时前
在Ubuntu中配置mysql,并允许外部访问数据库
数据库·mysql·ubuntu
Code apprenticeship1 小时前
怎么利用Redis实现延时队列?
数据库·redis·缓存
百度智能云技术站2 小时前
广告投放系统成本降低 70%+,基于 Redis 容量型数据库 PegaDB 的方案设计和业务实践
数据库·redis·oracle
装不满的克莱因瓶2 小时前
【Redis经典面试题六】Redis的持久化机制是怎样的?
java·数据库·redis·持久化·aof·rdb
axxy20002 小时前
leetcode之hot100---240搜索二维矩阵II(C++)
数据结构·算法
梦想平凡3 小时前
PHP 微信棋牌开发全解析:高级教程
android·数据库·oracle