Redis全文搜索教程之创建索引并关联源数据
创始人
2025-07-09 08:10:04
0

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

这里我们把被索引的 hash 或者 json 类型数据叫做源数据。

本文大纲如下,

图片图片

使用体验

简单场景下,用 RediSearch 来平替 Elasticsearch 的使用场景已经足够。像是 Elasticsearch 中常用的查询语法 AND 、OR 、IN 、NOT IN 、> 、< 、= 、like 等,在 RediSearch 中都是支持的。

此外 RediSearch 还支持聚合统计、停用词、文本标记和转义、同义词、标签、排序、向量查询、中文分词等。

就我个人来说,个人项目使用 RediSearch 作为全文搜索引擎已经够用了,它有占用内存低、索引建立快、查询数据性能足够高等优点。

后续发展

就目前官方对 RediSearch 的支持更新来看,

图片图片

RediSearch 官方更新频率图

最近一次提交记录在 12 月 17 号。

可以看到 RediSearch 的更新频率还是比较高的,而且是官方支持做的模块,不用担心后续无人维护。

虽然 Redis 天生支持分布式集群,但是 RediSearch 对 Redis 集群的支持还不完善,引用官方说明,

图片图片

官方针对 RediSearch 的集群支持问题,提供了一个 RediSearch 集群版本,但是这个版本只能在 Redis 企业版或者 Redis Cloud 上能使用,开源版还没有,这一点需要告诉大家。

遇到 bug

首先在使用 RediSearch 的过程中,遇到了 bug 并发现 bug 来源于 RediSearch,不要慌,也不要抱怨难用, 毕竟是开源项目,

图片图片

官方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 list) {
    int chunk = 200;
    List> partition = ListUtil.partition(list, chunk);
    AbstractPipeline pipelined = client.pipelined();
    for (List goodsList : partition) {
        for (Goods goods : goodsList) {
            RsGoodsDTO target = new RsGoodsDTO();
            MyBeanUtil.copyProperties(goods, target);
            Map 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 对于源数据关联的索引,要使用中文分词查询。

建立索引

RediSearch 通过提供一种简单且自动的方式在 Redis hash 类型数据结构上创建二级索引,并且内部极大地简化了这一过程。(最终会出现更多数据结构)

二级索引示意图二级索引示意图

如果我们要使用 RediSearch 查询商品 hash 结构里的 goodsName 字段,那么必须要对该字段建立索引。

Jedis 新建索引

所以这里,我给大家介绍下在 newbee-mall-pro 项目中,是如何建立索引的,代码逻辑在 GoodsServiceImpl.syncRs() 方法中,

// 定义索引结构
public boolean syncRs() {
    jedisSearch.dropIndex("idx:goods");
    Schema schema = new Schema()
            .addSortableTextField("goodsName", 1.0)
            .addSortableTextField("goodsIntro", 0.5)
            .addSortableNumericField("goodsId")
            .addSortableNumericField("goodsCategoryId")
            .addSortableNumericField("goodsSellStatus")
            .addSortableNumericField("sellingPrice")
            .addSortableNumericField("originalPrice")
            .addSortableTagField("tag", "|");
    jedisSearch.createIndex(Constants.GOODS_IDX_NAME, Constants.GOODS_IDX_PREFIX, schema);
}

上述代码中,我们对商品 hash 结构里的下方字段都建立了索引。

  • goodsName:文本类型,可排序,设置权重为 1.0
  • goodsIntro:文本类型,可排序,设置权重为 0.5
  • goodsId:数字类型,可排序
  • goodsCategoryId:数字类型,可排序
  • goodsSellStatus:数字类型,可排序
  • sellingPrice:数字类型,可排序
  • originalPrice:数字类型,可排序
  • tag:标签类型,可排序,设置分隔符为字符串 |

在 RediSerach 中可以添加的字段类型有 text、numberic、tag 等,可以设置是否排序。

并且还可以设置权重系数,表示该字段已加权。这对于在搜索操作期间为特定字段分配不同的重要性级别非常有用,通常就是在条件筛选完成后的打分排序阶段用于提升或者降低排名。

Redis 中的新建索引语法

当我们把上面的 Jedis 新建索引的代码转换为 Redis 中的语法后,如下

> FT.CREATE idx:goods ON hash PREFIX 1 "newbeemall:goods:" \
SCHEMA goodsName TEXT SORTABLE WEIGHT 1.0 \
SCHEMA goodsIntro TEXT SORTABLE WEIGHT 0.5 \
goodsId NUMERIC SORTABLE \
goodsCategoryId NUMERIC SORTABLE \
goodsSellStatus NUMERIC SORTABLE \
sellingPrice NUMERIC SORTABLE \
originalPrice NUMERIC SORTABLE \
tag TAG SORTABLE SEPARATOR "|"

现在我给大家详细介绍下这条命令:

  • FT.CREATE:RediSearch 中索引创建语法。
  • idx:goods:指定索引名称,索引名称将在所有键名称中使用,因此请保持简短。
  • ON hash:指定索引关联的结构类型。需要注意的是,在 RediSearch 2.0 中仅支持哈希结构,随着 RediSearch 更新,后续有望支持更多数据结构。
  • PREFIX 1 "newbeemall:goods:":指定索引的关联源数据的 key 前缀,可以指定多个前缀。
  • SCHEMA ...:字段定义,用于定义字段名称、类型、是否排序、权重等。可以定义多个字段。

如果你想了解更多关于 ft.search 的语法以及字段定义相关的只是,可以打开官方文档,

https://redis.io/docs/interact/search-and-query/basic-constructs/schema-definition

Redis 中查询索引定义

在 RediSearch 中要查询已经存在的索引详情也是很简单的,官方提供了 ft.info 索引名称 的语法,用来打印索引详情。

> FT.INFO idx:goods

相关内容

热门资讯

PHP新手之PHP入门 PHP是一种易于学习和使用的服务器端脚本语言。只需要很少的编程知识你就能使用PHP建立一个真正交互的...
网络中立的未来 网络中立性是什... 《牛津词典》中对“网络中立”的解释是“电信运营商应秉持的一种原则,即不考虑来源地提供所有内容和应用的...
各种千兆交换机的数据接口类型详... 千兆交换机有很多值得学习的地方,这里我们主要介绍各种千兆交换机的数据接口类型,作为局域网的主要连接设...
什么是大数据安全 什么是大数据... 在《为什么需要大数据安全分析》一文中,我们已经阐述了一个重要观点,即:安全要素信息呈现出大数据的特征...
全面诠释网络负载均衡 负载均衡的出现大大缓解了服务器的压力,更是有效的利用了资源,提高了效率。那么我们现在来说一下网络负载...
如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
P2P的自白|我不生产内容,我... 现在一提起P2P,人们就会联想到正在被有关部门“围剿”的互联网理财服务。×租宝事件使得劳...
Intel将Moblin社区控... 本周二,非营利机构Linux基金会宣布,他们将担负起Moblin社区的管理工作,而这之前,Mobli...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...