github: https://github.com/RedisJSON/RedisJSON website: https://oss.redis.com/redisjson/
RedisJSON是什么
RedisJSON是一个Redis模块,它实现了JSON数据交换标准ECMA-404,作为原生数据类型。它允许从Redis中存储、更新和获取JSON值.
特点
完全支持JSON标准 使用类似JSONPath的语法,用于在文档中选择元素 文档以二进制数据的形式存储在树结构中,允许快速访问子元素 所有JSON值类型都是原子操作
方式1: redis-server --loadmodule /usr/lib/redis/module/rejson.so 方式2: 在redis.conf中,添加一下内容: loadmodule /usr/lib/redis/module/rejson.so
运行
docker run -d -p 6379:6379 --name redis-redisjson -v /redisjson/data:/data redislabs/rejson:latest
进入容器
docker exec -it redis-redisjson bash 问题: the input device is not a TTY. If you are using mintty, try prefixing the command with 'winpty' winpty docker exec -it redis-redisjson bash
连接
redis-cli.exe -h 127.0.0.1 -p 6379
命令行操作
RedisJSON API命令
命令和子命令的名称是大写的,例如JSON.SET 和INDENT 强制参数用尖括号括起来,例如<path> 可选参数用方括号括起来,例如[index] 其他可选参数由三个句点字符表示,即... 管道字符|表示异或 ##标量命令 #设置json值 JSON.SET <key> <path> <json> [NX | XX] 说明: NX: 如果不存在就添加 XX: 如果存在就更新 #查询key的值 JSON.GET <key> [INDENT indentation-string] [NEWLINE line-break-string] [SPACE space-string] [path ...] 说明: 可以接受多个path,默认是root INDENT: 设置嵌套级别 NEWLINE: 每行末尾打印的字符串 SPACE: 设置key和value之间的字符串 JSON.GET myjsonkey INDENT "\t" NEWLINE "\n" SPACE " " . JSON.SET doc $ '{"a":2, "b": 3, "nested": {"a": 4, "b": null}}' JSON.GET doc $..b JSON.GET doc ..a $..b #查询指定路径下的多个key,不存在的key或path返回null JSON.MGET <key> [key ...] <path> JSON.SET doc1 $ '{"a":1, "b": 2, "nested": {"a": 3}, "c": null}' JSON.SET doc2 $ '{"a":4, "b": 5, "nested": {"a": 6}, "c": null}' JSON.MGET doc1 doc2 $..a #删除值 JSON.DEL <key> [path] 说明: 不存在的key或path会被忽略 返回integer #增加数字的值 JSON.NUMINCRBY <key> <path> <number> #数字乘法,过时了 JSON.NUMMULTBY <key> <path> <number> #追加字符串 JSON.STRAPPEND <key> [path] <json-string> #字符串的长度 JSON.STRLEN <key> [path] ##数组命令 #追加数组元素 JSON.ARRAPPEND <key> <path> <json> [json ...] #搜索指定元素在数组中第一次出现的位置,如果存在返回索引,不存在返回-1 JSON.ARRINDEX <key> <path> <json-scalar> [start [stop]] 说明: [start [stop]] 从start开始(包含)到stop(不包含)的范围 #在数组指定位置插入元素 JSON.ARRINSERT <key> <path> <index> <json> [json ...] 说明: index: 0是数组第一个元素,负数表示从末端开始计算 #数组的长度 JSON.ARRLEN <key> [path] 说明: 如果key或path不存在,返回null #删除返回数组中指定位置的元素 JSON.ARRPOP <key> [path [index]] 说明: index: 默认是-1,最后一个元素 #去掉元素,使其仅包含指定的包含范围的元素 JSON.ARRTRIM <key> <path> <start> <stop> ##对象命令 #返回对象中的key JSON.OBJKEYS <key> [path] #返回对象key的数量 JSON.OBJLEN <key> [path] ##模块命令 #返回json value的数据类型 JSON.TYPE <key> [path] #返回key的字节数 JSON.DEBUG MEMORY <key> [path]
字符串
#添加 127.0.0.1:6379> JSON.SET foo . '"bar"' OK #查询 127.0.0.1:6379> JSON.GET foo "\"bar\"" #类型 127.0.0.1:6379> JSON.TYPE foo "string" #字符串长度 127.0.0.1:6379> JSON.STRLEN foo (integer) 3 #字符串追加 127.0.0.1:6379> json.strappend foo . '"lish"' (integer) 7 127.0.0.1:6379> json.get foo "\"barlish\""
数字
#添加num 127.0.0.1:6379> json.set num . 0 OK #num加1 127.0.0.1:6379> json.numincrby num . 1 "1" #num加2.5 127.0.0.1:6379> json.numincrby num . 2.5 "3.5" #num减0.5 127.0.0.1:6379> json.numincrby num . -0.5 "3" #num乘10 127.0.0.1:6379> json.nummultby num . 10 "30" 127.0.0.1:6379> json.get num "30.0"
json数据
#添加json字符串 127.0.0.1:6379> JSON.SET user . '{"name":"lcj","age":23}' OK #查询 127.0.0.1:6379> JSON.GET user "{\"name\":\"lcj\",\"age\":23}" #数据类型 127.0.0.1:6379> JSON.TYPE user "object" #数据元素个数 127.0.0.1:6379> json.objlen user (integer) 2 #所有的key 127.0.0.1:6379> json.objkeys user 1) "name" 2) "age"
数组
#添加空数组 127.0.0.1:6379> json.set arr . [] OK #追加数据 127.0.0.1:6379> json.arrappend arr . true (integer) 1 127.0.0.1:6379> json.arrappend arr . '{"answer":42}' (integer) 2 127.0.0.1:6379> json.arrappend arr . null (integer) 3 #查询 127.0.0.1:6379> json.get arr "[true,{\"answer\":42},null]" #查询数组某个元素 127.0.0.1:6379> json.get arr [1].answer "42" #删除最后一个元素 127.0.0.1:6379> json.del arr [-1] (integer) 1 #指定位置插入数据 127.0.0.1:6379> json.arrinsert arr . 0 -2 -1 (integer) 4 127.0.0.1:6379> json.get arr "[-2,-1,true,{\"answer\":42}]" #删除元素,只保留指定范围的元素 127.0.0.1:6379> json.arrtrim arr . 2 3 (integer) 1 #获取数据并删除 127.0.0.1:6379> json.arrpop arr "true" 127.0.0.1:6379> json.arrpop arr (nil)
支持的客户端库
java操作
maven依赖
<dependency> <groupId>com.redislabs</groupId> <artifactId>jrejson</artifactId> <version>1.4.0</version> </dependency>
github地址
https://github.com/RedisJSON/JRedisJSON
java代码
import cn.hutool.core.lang.Console; import com.redislabs.modules.rejson.JReJSON; import com.redislabs.modules.rejson.Path; import org.junit.jupiter.api.Test; /** * <p> * RedisJson测试类 * </p> * * @author: liuchangjun * @since: 2021/12/22 15:50 */ public class RedisJsonTest { @Test public void test(){ // 获取连接 JReJSON client = new JReJSON("127.0.0.1", 6379); // 添加字符串(路径为根路径)并返回 client.set("name","lcj", Path.ROOT_PATH); String name = client.get("name"); Console.log("字符串name:{}",name); name = client.get("name", String.class, Path.of(".")); Console.log("字符串name:{}",name); name = client.get("name", String.class, Path.ROOT_PATH); Console.log("字符串name:{}",name); } }
使用json.debug memory key计算大小 字符串最少占用24字节 127.0.0.1:6379> json.set str . '""' OK 127.0.0.1:6379> json.debug memory str (integer) 24 数组最少占用24个字节 127.0.0.1:6379> json.set arr . [] OK 127.0.0.1:6379> json.debug memory arr (integer) 24 json对象最少占用72个字节 127.0.0.1:6379> json.set obj . {} OK 127.0.0.1:6379> json.debug memory obj (integer) 72
RedisJSON目前支持两种查询语法:JSONPath语法和RedisJSON第一个版本的路径语法。 RedisJSON根据路径查询的第一个字符决定使用哪种语法。如果查询以字符$开头,则使用JSONPath语法。否则,它默认为路径语法。 JSONPath: RedisJSON 2.0引入了JSONPath支持。 JSONPath查询可以解析JSON文档中的多个位置。在这种情况下,JSON命令将操作每个可能的位置。这是对遗留查询的重大改进,早期查询只在第一条路径上运行。 注意,在使用JSONPath时,命令响应的结构通常不同。 新语法支持括号表示法,允许在键名中使用特殊字符,如冒号“:”或空格。 Legacy Path syntax (RedisJSON v1): RedisJSON的第一个版本有以下实现。RedisJSON v2仍然支持它。 路径总是从JSON值的根开始。根由字符(.)表示。对于引用根的子级的路径,可以选择在路径前面加上根前缀。 要访问数组元素,请将其索引括在一对方括号内。索引是基于0的,0是数组的第一个元素。可以使用负偏移来访问从数组末端开始的元素。-1是数组中的最后一个元素 json key的规则: 必须以字符,$,_开头 可以包含字符,数字,$,_ 大小写敏感
1,索引json文档
除了存储JSON文档,还可以使用RediSearch模块进行索引,使用全文搜索功能。要使用此功能,必须安装两个模块:RedisJSON和RediSearch。
2,索引文档前置要求
3,创建索引
语法
FT.CREATE {index_name} ON JSON SCHEMA {json_path} AS {attribute} {type}
例子
FT.CREATE userIdx ON JSON SCHEMA $.user.name AS name TEXT $.user.tag AS country TAG
4,添加文档
一旦创建索引,任何预先存在的JSON文档或任何新的JSON文档(添加或修改)都会自动索引。索引是同步的 JSON.SET myDoc $ '{"user":{"name":"John Smith","tag":"foo,bar","hp":1000, "dmg":150}}'
5,搜索
#搜索名字含有John的用户 127.0.0.1:6379> FT.SEARCH userIdx '@name:(John)' 1) (integer) 1 2) "myDoc" 3) 1) "$" 2) "{\"user\":{\"name\":\"John Smith\",\"tag\":\"foo,bar\",\"hp\":1000,\"dmg\":150}}"
6,字段投影
默认FT.SEARCH返回整个文档 #返回指定的字段 FT.SEARCH userIdx '@name:(John)' RETURN 1 name #使用json路径表达式 127.0.0.1:6379> FT.SEARCH userIdx '@name:(John)' RETURN 1 $.user.hp 1) (integer) 1 2) "myDoc" 3) 1) "$.user.hp" 2) "1000" #返回属性别名 127.0.0.1:6379> FT.SEARCH userIdx '@name:(John)' RETURN 3 $.user.hp AS hitpoints 1) (integer) 1 2) "myDoc" 3) 1) "hitpoints" 2) "1000" #高亮 只要使用文本类型对任何属性进行索引,就可以高亮显示该属性。 127.0.0.1:6379> FT.SEARCH userIdx '@name:(John)' RETURN 1 name HIGHLIGHT FIELDS 1 name TAGS '<b>' '</b>' 1) (integer) 1 2) "myDoc" 3) 1) "name" 2) "<b>John</b> Smith"
7,聚合
聚合是一个强大的功能。使用它生成统计信息或构建方面查询。LOAD参数接受JSON路径表达式。管道中可以使用任何值(即使没有索引)。 FT.AGGREGATE userIdx * LOAD 6 $.user.hp AS hp $.user.dmg AS dmg APPLY '@hp-@dmg' AS points 1) (integer) 1 2) 1) "hp" 2) "1000" 3) "dmg" 4) "150" 5) "points" 6) "850"
8,索引限制
1,无法为JSON对象或JSON数组进行索引。
要索引,JSONPath表达式必须返回单个标量值(字符串或数字)。如果JSONPath表达式返回一个对象或数组,它将被忽略。 #创建索引 FT.CREATE orgIdx ON JSON SCHEMA $.address[0] AS a1 TEXT $.address[1] AS a2 TEXT #添加文档 JSON.SET org:1 $ '{"name": "Headquarters","address": ["Suite 250","Mountain View"],"cp": "CA 94040"}' #搜索 FT.SEARCH orgIdx "suite 250" FT.SEARCH orgIdx "Mountain"
2,将json字符串和数字索引为 TEXT 和NUMERIC
只能将JSON字符串索引为文本、标记或地理位置 只能将JSON数字索引为数字 JSON布尔值只能作为TAG索引 忽略NULL
3,TAG上不支持排序
127.0.0.1:6379> FT.CREATE orgIdx2 ON JSON SCHEMA $.cp[0] AS cp TAG SORTABLE (error) On JSON, cannot set tag field to sortable - cp