路径

访问 JSON 文档中的特定元素

路径允许您访问 JSON 文档中的特定元素。由于不存在 JSON 路径语法标准,Redis JSON 实现了自己的语法。JSON 的语法基于常见的最佳实践,有意类似于 JSONPath

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

JSON 会根据路径查询的第一个字符来确定使用哪种语法。如果查询以字符 `$` 开头,则使用 JSONPath 语法。否则,默认使用旧版路径语法。

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

JSONPath 支持

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

JSONPath 查询可以解析到 JSON 文档中的多个位置。在这种情况下,JSON 命令会对所有可能的位置执行操作。这是对 旧版路径 查询的重大改进,旧版路径查询只对第一个路径进行操作。

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

新语法支持方括号表示法,允许使用冒号 `:` 或空格等特殊字符作为键名。

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

JSON.GET store '$.inventory["mountain_bikes"]'

JSONPath 语法

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

语法元素 描述
$ 根(最外层的 JSON 元素),路径的起点。
. 或 [] 选择子元素。
.. 递归地遍历 JSON 文档。
* 通配符,返回所有元素。
[] 下标运算符,访问数组元素。
[,] 联合,选择多个元素。
[start:end:step] 数组切片,其中 startendstep 是索引值。您可以省略切片中的值(例如,[3:][:8:2])以使用默认值:start 默认设置为第一个索引,end 默认设置为最后一个索引,step 默认设置为 `1`。使用 `[*]` 或 `[:]` 选择所有元素。
?() 筛选 JSON 对象或数组。支持比较运算符(==, !=, <, <=, >, >=, =~)、逻辑运算符(&&, ||)和括号((, )).
() 脚本表达式。
@ 当前元素,用于筛选或脚本表达式。

JSONPath 示例

以下 JSONPath 示例使用此 JSON 文档,该文档存储有关商店库存中商品的详细信息

{
    "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 文档

访问示例

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

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

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

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

您可以使用数组切片从数组中选择一定范围的元素。此示例返回前 2 辆山地自行车的名称

筛选表达式 `?()` 允许您根据某些条件选择 JSON 元素。您可以在这些表达式中使用比较运算符(`==`、`!=`、`<`、`<=`、`>`、`>=`,从 v2.4.2 版开始,还有 `=~`)、逻辑运算符(`&&`、`||`)和括号(`(`、`)`)。筛选表达式可以应用于数组或对象,遍历数组中的所有 元素 或对象中的所有 ,只检索与筛选条件匹配的元素。

筛选条件中的路径使用点表示法,使用 `@` 表示当前数组元素或当前对象值,或使用 `$` 表示顶级元素。例如,使用 `@.key_name` 引用嵌套值,使用 `$.top_level_key_name` 引用顶级值。

从 v2.4.2 版开始,您可以使用比较运算符 `=~` 将左侧字符串值的路径与右侧正则表达式模式进行匹配。有关更多信息,请参见 支持的正则表达式语法文档

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

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

其他 JSONPath 引擎可能在斜杠之间使用正则表达式模式(例如,`/foo/`),它们的匹配是精确的。它们可以使用像 `/.foo.*/` 这样的正则表达式模式执行部分匹配。

筛选示例

在以下示例中,筛选器只返回价格低于 3000 美元且重量低于 10 的山地自行车

此示例筛选库存以查找由合金制成的自行车的型号名称

此示例(从 v2.4.2 版开始有效)仅筛选材料以 “al-” 开头的自行车,使用正则表达式匹配。请注意,此匹配不区分大小写,因为正则表达式模式 `"(?i)al"` 中有前缀 `(?i)`

您还可以使用 JSON 对象本身的属性指定正则表达式模式。例如,我们可以为每辆山地自行车添加一个名为 `regex_pat` 的字符串属性,其值为 `"(?i)al"` 以匹配材料,如前面的示例所示。然后,我们可以将 `regex_pat` 与自行车的材料进行匹配

更新示例

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

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

您可以使用筛选表达式只更新与某些条件匹配的 JSON 元素。以下示例将任何自行车的价格设置为 1500 美元,如果其价格已经低于 2000 美元

JSONPath 查询也适用于接受路径作为参数的其他 JSON 命令。例如,您可以使用 JSON.ARRAPPEND 为一组耳机添加新的颜色选项

旧版路径语法

RedisJSON v1 具有以下路径实现。JSON v2 除了 JSONPath 之外,仍然支持这种旧版路径。

路径始终从 Redis JSON 值的根开始。根由句点字符 (`.`) 表示。对于引用根子元素的路径,可以选择在路径前添加根。

Redis JSON 支持点表示法和方括号表示法来访问对象键。以下路径引用 headphones,它是根下 inventory 的子元素

  • .inventory.headphones
  • inventory["headphones"]
  • ['inventory']["headphones"]

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

JSON 键名和路径兼容性

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

虽然 JSON 可以存储包含任意键名的对象,但您只能在这些键符合以下命名语法规则时使用旧版路径访问它们

  1. 名称必须以字母、美元符号 (`) 或下划线 (_) 字符开头
  2. 名称可以包含字母、数字、美元符号和下划线
  3. 名称区分大小写

路径评估的时间复杂度

在路径中搜索(导航到)元素的时间复杂度由以下因素计算

  1. 子级级别 - 路径中的每个级别都会增加一次搜索
  2. 键搜索 - O(N),其中 N 是父对象中的键数
  3. 数组搜索 - O(1)

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

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

RATE THIS PAGE
Back to top ↑