Redis查询之RediSearch和RedisJSON讲解

您所在的位置:网站首页 天际资本可靠吗 Redis查询之RediSearch和RedisJSON讲解

Redis查询之RediSearch和RedisJSON讲解

2024-01-03 11:33| 来源: 网络整理| 查看: 265

文章目录 1 Redis查询1.1 RedisMod介绍1.2 安装Redis1.3 RediSearch+RedisJSON安装1.3.1 下载安装1.3.2 修改配置 1.4 RedisJSON操作1.4.1 基本操作1.4.1.1 保存操作JSON.SET1.4.1.2 读取操作JSON.GET1.4.1.3 批量读取操作JSON.MGET1.4.1.4 删除操作JSON.DEL1.4.1.5 其他命令1.4.1.6 综合操作 1.4.2 Java 来操作 redis Json 1.5 RediSearch操作1.5.1 查询语法1.5.2 建立索引1.5.3 操作1.5.4 Java 中操作RediSearch1.5.4.1 Jedis 创建 RediSearch 客户端1.5.4.2 Jedis 创建索引1.5.4.3 Jedis 添加索引源数据1.5.4.4 Jedis 中文查询

1 Redis查询 1.1 RedisMod介绍

首先介绍下RedisMod这个东西,它是一系列Redis的增强模块。有了RedisMod的支持,Redis的功能将变得非常强大。目前RedisMod中包含了如下增强模块:

RediSearch:一个功能齐全的搜索引擎;RedisJSON:对JSON类型的原生支持;RedisTimeSeries:时序数据库支持;RedisGraph:图数据库支持;RedisBloom:概率性数据的原生支持;RedisGears:可编程的数据处理;RedisAI:机器学习的实时模型管理和部署。 1.2 安装Redis

Redis这些模块都是依赖于Redis,因此先要安装Redis 点击了解Redis单机安装 点击了解Redis集群安装

1.3 RediSearch+RedisJSON安装 1.3.1 下载安装

下载RediSearch+RedisJSON地址:https://redis.com/redis-enterprise-software/download-center/software/ 在这里插入图片描述 在 redis 安装目录下新建 module 文件夹,把获取到的rejson.so和module-enterprise.so(可以重命名为redissearch.so)文件 放到 module 文件夹中

1.3.2 修改配置 修改 文件 为可执行权限 chmod +x rejson.so chmod +x module-enterprise.so 修改 redis.conf,搜索 loadmodule loadmodule /root/software/redis-6.0.6/module/rejson.so loadmodule /root/software/redis-6.0.6/module/module-enterprise.so 重启 redis /usr/local/redis-6.2.6/bin/redis-cli -a 123456 shutdown /usr/local/redis-6.2.6/bin/redis-server conf/redis.conf 1.4 RedisJSON操作

命令行体验 json 的操作

1.4.1 基本操作 1.4.1.1 保存操作JSON.SET

语法:

JSON.SET [NX | XX]

参数说明:

对于新的Key,path需要使用$或 .对于已经存在Key,在进行保存操作之后,原来path路径的值将会被替换掉;NX:表示只有Key不存在,才执行保存操作XX:表示只有Key存在,才执行保存操作通过命令type doc可以查看到存储进去的数据是ReJSON-RL类型 1.4.1.2 读取操作JSON.GET

语法:

JSON.GET [INDENT indentation-string] [NEWLINE line-break-string] [SPACE space-string] [path ...]

参数说明:

允许使用多个path进行查询INDENT 查询结果替换掉默认缩进字符(用于返回Pretty-formatted JSON)NEWLINE 查询结果替换掉默认换行符(用于返回Pretty-formatted JSON)SPACE 查询结果替换掉默认空格(用于返回Pretty-formatted JSON)获取JSON对象中的属性时需要以.开头 1.4.1.3 批量读取操作JSON.MGET

语法:

JSON.MGET [key ...]

参数说明:

最后一个参数作为path进行处理遍历每一个Key的path,如果不存在,则返回null

例子:

先保存两条记录 JSON.SET doc1 $ '{"a":1, "b": 2, "nested": {"a": 3}, "c": null}' JSON.SET doc2 $ '{"a":4, "b": 5, "nested": {"a": 6}, "c": null}' 再进行mget操作 JSON.MGET doc1 doc2 $..a 执行结果: 1) "[1,3]" 2) "[4,6]" 1.4.1.4 删除操作JSON.DEL

语法:

JSON.DEL [path]

参数说明:

path是可选的,如果没有输入,则默认整个Key删除掉

例子:

JSON.DEL doc $..a 结果: "2" 1.4.1.5 其他命令

除了上面的几种常见操作,官方还支持如下命令,官方命令地址:https://redis.io/docs/stack/json/commands/

常用命令: JSON.NUMINCRBY,JSON.NUMMULTBY,JSON.STRAPPEND,JSON.STRLEN 数组命令: JSON.ARRAPPEND,JSON.ARRINDEX,JSON.ARRINSERT,JSON.ARRLEN,JSON.ARRPOP,JSON.ARRTRIM 对象命令: JSON.OBJKEYS,JSON.OBJLEN 组件命令 JSON.TYPE,JSON.DEBUG,JSON.FORGET,JSON.RESP

1.4.1.6 综合操作 创建一个 json_1 127.0.0.1:6379> JSON.SET json_1 . '{"name":"zz","age":22,"msg":"hello"}' OK 设置 json_1 的 key=name 的值为 zhangsan 127.0.0.1:6379> JSON.SET json_1 .name '"zhangsan"' OK 获得整个 json_1 127.0.0.1:6379> JSON.GET json_1 "{\"name\":\"zhangsan\",\"age\":22,\"msg\":\"hello\"}" 获得 json_1 键为 name 的值 127.0.0.1:6379> JSON.GET json_1 .name "\"zhangsan\"" 往 json_1 中添加一个数组对象 127.0.0.1:6379> json.set json_1 .list '[2,3,4]' OK 往 json_1 的 list 对象中添加一个元素 6 127.0.0.1:6379> json.arrappend json_1 .list 6 (integer) 4 查看所有元素 127.0.0.1:6379> json.get json_1 "{\"name\":\"zhangsan\",\"age\":22,\"msg\":\"hello\",\"list\":[2,3,4,6]}"

体验下来,感觉 Redis 原生支持 json 之后,对于 redis 的操作更加灵活了。

想象空间更大了,一切复杂信息的存储皆可 JSON,并且操作十分简单,省去了序列化、反序列化的操作,

1.4.2 Java 来操作 redis Json

当然我们还是要在一个 Java 工程中去操作一下:

package com.kkarch.rejson; import com.redislabs.modules.rejson.JReJSON; import com.redislabs.modules.rejson.Path; import redis.clients.jedis.Jedis; import java.util.Arrays; public class ReJsonMain { public static void main(String[] args) { Jedis jedis = new Jedis("192.168.0.110",6379); jedis.auth("123456"); JReJSON redisClient = new JReJSON(jedis); System.out.println("初始化 json"); redisClient.set("json_2",new Object()); redisClient.set("json_2","zhangsan",new Path(".name")); redisClient.set("json_2",21,new Path(".age")); redisClient.set("json_2","hello",new Path(".msg")); redisClient.set("json_2",Arrays.asList(9,8,7),new Path(".arr")); Object result = null; result = redisClient.get("json_2"); System.out.println(result); System.out.println("设置 name=lisi"); redisClient.set("json_2","lisi",new Path(".name")); result = redisClient.get("json_2"); System.out.println(result); System.out.println("在数组追加一个值:21"); redisClient.arrAppend("json_2", new Path(".arr"), 21); result = redisClient.get("json_2"); System.out.println(result); } } 结果: 初始化 json {name=zhangsan, age=21.0, msg=hello, arr=[9.0, 8.0, 7.0]} 设置 name=lisi {name=lisi, age=21.0, msg=hello, arr=[9.0, 8.0, 7.0]} 在数组追加一个值:21 {name=lisi, age=21.0, msg=hello, arr=[9.0, 8.0, 7.0, 21.0]} 1.5 RediSearch操作

通过RediSearch模块,Redis可以变成一个功能强大的全文搜索引擎,并且原生支持中文搜索,下面我们就来体验下

1.5.1 查询语法

RediSearch的搜索语法比较复杂,不过我们可以对比SQL来使用它,具体可以参考如下

SQL ConditionRediSearch Equivalent注释where x=‘foo’ and y=‘bar’@x:foo @y:barfor less ambiguity use (@x:foo) (@y:bar)where x=‘foo’ and y!=‘bar’@x:foo -@y:barwhere x=‘foo’ or y=‘bar’(@x:foo) | (@y:bar)where x in (‘foo’ ,‘bar’ )@x:(foo| bar)quotes means exact phrasewhere y=‘foo’ and x not in (‘foo’ ,‘bar’ )@y:foo (-@x:foo)(-@x:bar)where num between 10 and 20@num:[10:20]where num >=10@num:[10 +inf]where num > 10@num:[(10 +inf]where num < 10@num:[-inf (10]where num 20@num:[-inf (10] | @num:[(20 +inf ]where name like ‘john%’@name:john* 1.5.2 建立索引

使用 RediSearch 来搜索数据之前,我们得先创建下索引,建立索引的语法有点复杂,我们先来看下;

FT.CREATE {index} [ON {data_type}] [PREFIX {count} {prefix} [{prefix} ..] [LANGUAGE {default_lang}] SCHEMA {identifier} [AS {attribute}] [TEXT | NUMERIC | GEO | TAG ] [CASESENSITIVE] [SORTABLE] [NOINDEX]] ...

使用FT.CREATE命令可以建立索引,语法中的参数意义如下;

index:索引名称;data_type:建立索引的数据类型,目前支持JSON或者HASH两种;PREFIX:通过它可以选择需要建立索引的数据前缀,比如PREFIX 1 "product:" 表示为键中以product:为前缀的数据建立索引;LANGUAGE:指定TEXT类型属性的默认语言,使用chinese可以设置为中文;SCHEMA:索引的字段identifier:指定属性名称;attribute:指定属性别名;TEXT | NUMERIC | GEO | TAG:这些都是属性可选的类型;SORTABLE:指定属性可以进行排序。

看了语法可能不太好理解,直接对一个商品数据建立索引试试就懂了;

FT.CREATE productIdx ON JSON PREFIX 1 "product:" LANGUAGE chinese SCHEMA $.id AS id NUMERIC $.name AS name TEXT $.subTitle AS subTitle TEXT $.price AS price NUMERIC SORTABLE $.brandName AS brandName TAG 1.5.3 操作

建立完索引后,我们就可以使用FT.SEARCH对数据进行查看了,比如使用*可以查询全部;

FT.SEARCH productIdx *

由于我们设置了price字段为SORTABLE,我们可以以price降序返回商品信息

FT.SEARCH productIdx * SORTBY price DESC

指定返回的字段;

FT.SEARCH productIdx * RETURN 3 name subTitle price

我们把brandName设置为了TAG类型,我们可以使用如下语句查询品牌为小米或苹果的商品;

FT.SEARCH productIdx '@brandName:{小米 | 苹果}'

由于price是NUMERIC类型,我们可以使用如下语句查询价格在500~1000的商品;

FT.SEARCH productIdx '@price:[500 1000]'

还可以通过前缀进行模糊查询,类似于SQL中的LIKE,使用*表示;

FT.SEARCH productIdx '@name:小米*'

在FT.SEARCH中直接指定搜索关键词,可以对所有TEXT类型的属性进行全局搜索,支持中文搜索,比如我们搜索下包含黑色字段的商品;

FT.SEARCH productIdx '黑色'

当然我们也可以指定搜索的字段,比如搜索副标题中带有红色字段的商品;

FT.SEARCH productIdx '@subTitle:红色'

通过FT.DROPINDEX命令可以删除索引,如果加入DD选项的话,会连数据一起删除;

FT.DROPINDEX productIdx

通过FT.INFO命令可以查看索引状态;

FT.INFO productIdx 1.5.4 Java 中操作RediSearch

对于 Java 项目直接选用 Jedis4.0 以上版本就可以使用 RediSearch 提供的搜索功能,Jedis 在 4.0 以上版本自动支持 RediSearch,编写 Jedis 连接 RediSearch 测试用例,用 RediSearch 命令创建如下,

1.5.4.1 Jedis 创建 RediSearch 客户端 @Bean public UnifiedJedis unifiedJedis(GenericObjectPoolConfig jedisPoolConfig) { UnifiedJedis client; if (StringUtils.isNotEmpty(password)) { client = new JedisPooled(jedisPoolConfig, host, port, timeout, password, database); } else { client = new JedisPooled(jedisPoolConfig, host, port, timeout, null, database); } return client; } 1.5.4.2 Jedis 创建索引 Schema schema = new Schema() .addSortableTextField("goodsName", 1.0) .addSortableTagField("tag", "|"); IndexDefinition rule = new IndexDefinition(IndexDefinition.Type.HASH) .setPrefixes("idx:goods") .setLanguage("chinese"); # 设置支持中文分词 client.ftCreate(idxName, IndexOptions.defaultOptions().setDefinition(rule), schema); 1.5.4.3 Jedis 添加索引源数据 public boolean addGoodsIndex(String keyPrefix, Goods goods) { Map hash = MyBeanUtil.toMap(goods); hash.put("_language", "chinese"); client.hset("idx:goods" + goods.getGoodsId(), MyBeanUtil.toMap(goods)); return true; } 1.5.4.4 Jedis 中文查询 public SearchResult search(String goodsIdxName, SearchObjVO searchObjVO, Page page) { // 查询关键字 String keyword = searchObjVO.getKeyword(); String queryKey = String.format("@goodsName:(%s)", keyword); Query q = new Query(queryKey); String sort = searchObjVO.getSidx(); String order = searchObjVO.getOrder(); // 查询是否排序 if (StringUtils.isNotBlank(sort)) { q.setSortBy(sort, Constants.SORT_ASC.equals(order)); } // 设置中文分词查询 q.setLanguage("chinese"); // 设置分页 q.limit((int) page.offset(), (int) page.getSize()); // 返回查询结果 return client.ftSearch(goodsIdxName, q); }


【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3