Redis全文搜索教程之创建索引并关联源数据

redis 全文搜索是依赖于 Redis 官方提供的 RediSearch 来实现的 。RediSearch 提供了一种简单快速的方法对 hash 或者 json 类型数据的任何字段建立二级索引,然后就可以对被索引的 hash 或者 json 类型数据字段进行搜索和聚合操作 。
这里我们把被索引的 hash 或者 json 类型数据叫做源数据 。
本文大纲如下,

Redis全文搜索教程之创建索引并关联源数据

文章插图
图片
使用体验简单场景下,用 RediSearch 来平替 Elasticsearch 的使用场景已经足够 。像是 Elasticsearch 中常用的查询语法 AND 、OR 、IN 、NOT IN 、> 、< 、= 、like 等,在 RediSearch 中都是支持的 。
此外 RediSearch 还支持聚合统计、停用词、文本标记和转义、同义词、标签、排序、向量查询、中文分词等 。
就我个人来说,个人项目使用 RediSearch 作为全文搜索引擎已经够用了 , 它有占用内存低、索引建立快、查询数据性能足够高等优点 。
后续发展【Redis全文搜索教程之创建索引并关联源数据】就目前官方对 RediSearch 的支持更新来看,
Redis全文搜索教程之创建索引并关联源数据

文章插图
图片
RediSearch 官方更新频率图
最近一次提交记录在 12 月 17 号 。
可以看到 RediSearch 的更新频率还是比较高的,而且是官方支持做的模块,不用担心后续无人维护 。
虽然 Redis 天生支持分布式集群,但是 RediSearch 对 Redis 集群的支持还不完善,引用官方说明,
Redis全文搜索教程之创建索引并关联源数据

文章插图
图片
官方针对 RediSearch 的集群支持问题,提供了一个 RediSearch 集群版本,但是这个版本只能在 Redis 企业版或者 Redis Cloud 上能使用,开源版还没有 , 这一点需要告诉大家 。
遇到 bug首先在使用 RediSearch 的过程中,遇到了 bug 并发现 bug 来源于 RediSearch,不要慌,也不要抱怨难用,毕竟是开源项目,
Redis全文搜索教程之创建索引并关联源数据

文章插图
图片
官方issue列表
大家可以看到 issue 列表中有很多 bug 没有解决 。
不过本着开源共进的精神,希望大家发现了 bug 后 , 第一时间在 RediSearch 官方 Github 上提个 issue,方便官方发现并解决问题 。
RediSearch Github 仓库地址:https://github.com/RediSearch/RediSearch
下面我给大家用 newbee-mall-pro 项目作为样本,给大家介绍下如何创建一个索引并关联源数据 。
newbee-mall-pro 项目地址:https://github.com/wayn111/newbee-mall-pro
添加源数据在 newbee-mall-pro 项目中,已经将商品数据以 hash 类型存入了 Redis 中 , 
其中 , 我们对于 key 名称的定义规则是按照 newbee_mall:goods: + 商品ID 。
这里我们的 key 名称定义规则很重要,RediSearch 创建索引会基于 key 名称前缀来生成 。
hash 类型的 value 包含属性如下,
  • goodsId : 商品 ID,唯一属性,由数据库商品表主键生成
  • goodsName : 商品名称
  • goodsIntro : 商品简介
  • goodsCategoryId : 商品分类 ID,唯一属性,由数据库商品分类表主键生成
  • goodsSellStatus : 商品上架状态 , 0 代表下架,1 代表上架
  • sellingPrice : 商品售价
  • originalPrice : 商品原价
  • tag : 商品标签
在 newbee-mall-pro 中,添加源数据的方法已经写好了,代码逻辑在 JedisSearch.addGoodsListIndex() 方法里,
public boolean addGoodsListIndex(String keyPrefix, List<Goods> list) {int chunk = 200;List<List<Goods>> partition = ListUtil.partition(list, chunk);AbstractPipeline pipelined = client.pipelined();for (List<Goods> goodsList : partition) {for (Goods goods : goodsList) {RsGoodsDTO target = new RsGoodsDTO();MyBeanUtil.copyProperties(goods, target);Map<String, String> hash = MyBeanUtil.toMap(target);// 支持中文hash.put("_language", Constants.GOODS_IDX_LANGUAGE);pipelined.hset(keyPrefix + goods.getGoodsId(), hash);}}pipelined.sync();return true;}上诉代码中,其实就是把 list 商品列表以 hash 类型的数据结构写进 Redis 中 , 并且为了加快写入速度,使用了 Redis 提供的管道操作 。
需要注意的就是 hash 类型中新增了一个 _language 字段,用于指定 RediSearch 对于源数据关联的索引,要使用中文分词查询 。


推荐阅读