Redis怎么搞模糊查询还能分页,感觉挺实用的功能分享
- 问答
- 2025-12-24 14:05:09
- 9
说到Redis,大家首先想到的就是快,常用来做缓存,但它主要是键值对存储,不像数据库那样有直接的like查询和limit分页,通过巧妙使用Redis提供的一些数据结构,完全可以实现类似“模糊查询+分页”的效果,而且性能非常高,这在处理一些需要快速过滤和浏览的热数据场景时,非常实用。
这里分享几种常见且实用的方法,咱们由浅入深地说。
使用有序集合(ZSet)配合扫描(ZSCAN)
这个方法的思路是,把我们要查询的数据作为成员(member)存放在一个有序集合里,分数(score)可以用来排序,比如用时间戳,然后利用ZSCAN命令进行模糊匹配。
具体怎么搞呢?
-
准备数据: 假设我们有一堆用户昵称需要被模糊搜索,我们把所有昵称作为成员(member)放入一个叫
user:nicknames的ZSet中,分数可以统一设为0,或者如果你希望按热度、时间排序,可以设置成对应的数值。- 命令示例:
ZADD user:nicknames 0 "张三" 0 "张无忌" 0 "李四" 0 "李小龙"
- 命令示例:
-
进行模糊查询和分页:
ZSCAN命令可以遍历ZSet,并且支持通配符匹配,它返回的结果是一个游标和一批匹配的成员。- 模糊查询: 比如我们要找所有以“张”开头的昵称,我们可以使用
ZSCAN命令,匹配模式设为张*。 - 分页:
ZSCAN命令的游标机制天然支持分页,第一次调用时,游标从0开始,命令会返回一个新的游标和一部分数据,下次查询时带上这个新游标,就能获取下一批数据,直到游标变回0,表示遍历结束。
- 模糊查询: 比如我们要找所有以“张”开头的昵称,我们可以使用
操作示例: 假设我们要分页查询“张”开头的用户,每页2条。

- 第一页:
ZSCAN user:nicknames 0 MATCH "张*" COUNT 2- 返回结果可能包含游标(比如
18)和成员["张三", "张无忌"]。
- 返回结果可能包含游标(比如
- 第二页:
ZSCAN user:nicknames 18 MATCH "张*" COUNT 2- 因为匹配项可能就两个,所以这次返回的游标可能就是
0,表示没有更多数据了。
- 因为匹配项可能就两个,所以这次返回的游标可能就是
优点:
- 实现相对简单,利用了Redis原生命令。
- 适合数据量不是特别巨大的场景。
缺点:
- 如果ZSet非常大,
ZSCAN的效率可能会受到影响,因为它本质是遍历。 - 分页的“页”的大小(COUNT参数)只是个提示,Redis返回的数据量可能略多于或少于指定值,需要客户端做简单处理。
使用集合(Set)或有序集合(ZSet)建立索引
这个方法更高效,尤其适合数据量大、查询频繁的场景,核心思想是“空间换时间”,提前为可能被搜索的字段建立好索引。
具体怎么搞?
我们还是以搜索用户昵称为例,但这次用户信息是存储在Hash结构里的,键名是user:1, user:2等。

-
建立索引: 我们为昵称的每个可能的前缀(或者分词)建立索引集合。
- 比如用户“张三”,我们将其昵称按前缀拆分(可以按字,也可以按拼音首字母):
- 前缀为“张”的集合:
index:nickname:张 - 前缀为“张三”的集合:
index:nickname:张三
- 前缀为“张”的集合:
- 将用户ID(比如
1)加入到这些集合中:SADD index:nickname:张 1,SADD index:nickname:张三 1。
- 比如用户“张三”,我们将其昵称按前缀拆分(可以按字,也可以按拼音首字母):
-
进行模糊查询:
- 当用户输入“张”进行搜索时,我们直接取
index:nickname:张这个集合,里面就包含了所有昵称以“张”开头的用户ID。 - 如果输入“张三”,就取
index:nickname:张三这个更精确的集合。
- 当用户输入“张”进行搜索时,我们直接取
-
实现分页:
- 拿到索引集合后(比如
index:nickname:张),我们可以使用SMEMBERS获取所有ID(如果集合不大),但更优雅的方式是使用SORT命令。 - 我们可以使用
SORT index:nickname:张 BY nosort GET user:*->nickname LIMIT 0 2。 - 这个命令的意思是:对集合
index:nickname:张进行排序(BY nosort表示不排序,按存储顺序),然后通过GET指令去取出每个ID对应的Hash结构中的昵称字段,最后用LIMIT实现分页。
- 拿到索引集合后(比如
优点:
- 查询速度极快,几乎是O(1)的复杂度,因为直接定位到了索引集合。
- 非常适合前缀匹配型的模糊查询。
缺点:
- 需要额外的存储空间来存放索引。
- 写入数据时(新增、修改昵称)需要维护索引,会增加写操作的复杂度,比如改昵称,需要从旧索引集合中删除ID,再加入新的索引集合。
使用RedisSearch模块(终极利器)

如果条件允许,这是最强大、最省心的方案,RedisSearch是一个外部模块,为Redis提供了完整的全文搜索和二级索引功能,就像在Redis里内置了一个搜索引擎。
它能做什么?
- 创建索引: 你可以定义一个索引模式,指定哪些Hash字段需要被索引,以及索引类型(文本、数字、标签等)。
- 自动管理: 之后,你往对应的Hash里添加数据时,RedisSearch会自动更新索引,无需手动维护。
- 强大查询: 支持丰富的查询语法,包括模糊查询(通配符)、联合查询、范围查询、排序等。
- 直接分页: 查询命令直接支持
LIMIT offset count参数,实现完美的分页。
操作示例(简化概念):
- 创建索引:
FT.CREATE user_idx ON HASH PREFIX 1 user: SCHEMA nickname TEXT - 插入数据:
HSET user:1 nickname "张三" - 模糊查询加分页:
FT.SEARCH user_idx "张*" LIMIT 0 2
优点:
- 功能强大,媲美专业搜索引擎。
- 使用简单,无需在应用层处理复杂的索引逻辑。
- 性能优异。
缺点:
- 需要安装RedisSearch模块,对Redis环境有要求(比如云服务商可能不支持或需额外收费)。
- 小打小闹,数据量不大:用ZScan方法,简单快捷。
- 追求高性能,查询模式固定(如前缀搜索):用预建索引方法,空间换时间,效果显著。
- 不差钱,需求复杂,想要一劳永逸:直接上RedisSearch,这是最正统、最专业的解决方案。
希望这些直接的方法分享能给你带来启发,具体用哪种,还得看你的实际业务场景和技术选型。
本文由凤伟才于2025-12-24发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://haoid.cn/wenda/67588.html
