Redis 数值范围查询(Numeric Range Queries)的实现
作者:Hello.Reader
一、基本语法
1. 普通范围查询
使用查询字符串语法,将字段名及上下界写在一对方括号内:
FT.SEARCH idx "@field:[start end]"
start和end默认均包含(inclusive)。- 例如,检索价格在 500 到 1000 区间的商品:
FT.SEARCH idx:bicycle "@price:[500 1000]"
2. 排除边界
若要排除上(或下)界,在该值前加左括号 (:
FT.SEARCH idx "@price:[(1000 +inf]"
- 上例匹配
price > 1000。 -inf/+inf可用于定义“下不封顶”或“上不封顶”的开/闭区间。
二、FILTER 与执行计划差异
除了在查询字符串中直接指定范围,还可借助 FILTER 子句:
FT.SEARCH idx "*" FILTER price 500 1000
FILTER会在查询解析(如全文*)完成后再执行数值过滤。- 当索引包含数值字段且仅依赖数值过滤时,若直接在查询字符串中指定范围,RediSearch 能利用索引跳过不匹配文档,性能通常更佳;
- 若查询中包含复杂子句或聚合,
FILTER提供了灵活的后置过滤方案。
三、排序与分页
1. SORTBY
默认情况下,结果按文档出现顺序返回。可用 SORTBY 按数值字段排序:
FT.SEARCH idx:bicycle "@price:[-inf 2000]" SORTBY price ASC LIMIT 0 5
ASC/DESC指定升序或降序。- 未显式排序时,可视为按文档 ID 或添加顺序返回。
2. LIMIT
LIMIT offset count控制返回窗口,实现分页或“滚动”访问大结果集;- Redis 默认只返回前 10 条,若需完整结果,务必配合
LIMIT。
四、典型示例
假设已创建如下索引:
FT.CREATE idx:bicycle ON JSON PREFIX 1 bicycle:
SCHEMA $.price AS price NUMERIC SORTABLE
$.brand AS brand TEXT SORTABLE
$.model AS model TEXT SORTABLE
并已插入若干文档。
示例1:500 ≤ price ≤ 1000
FT.SEARCH idx:bicycle "@price:[500 1000]"
示例2:price > 1000
FT.SEARCH idx:bicycle "@price:[(1000 +inf]"
示例3:price ≤ 2000,返回最便宜的 5 辆
FT.SEARCH idx:bicycle "@price:[-inf 2000]" SORTBY price ASC LIMIT 0 5
示例4:使用 FILTER(等价于示例1)
FT.SEARCH idx:bicycle "*" FILTER price 500 1000
五、多语言客户端示例
以下以 Python 和 Go 为例,展示如何在客户端执行数值范围查询。
Python(redis-py + redisearch-py)
from redis import Redis
from redis.commands.search.field import NumericField, TextField
from redis.commands.search.query import Query
r = Redis()
# 假设已创建索引
q = Query("@price:[500 1000]").sort_by("price", asc=True).paging(0, 10)
res = r.ft("idx:bicycle").search(q)
print(res.total, res.docs)
Go(go-redis + redisearch)
import (
"fmt"
"github.com/RediSearch/redisearch-go/redisearch"
)
client := redisearch.NewClient("localhost:6379", "idx:bicycle")
// 构造查询:500 <= price <= 1000,按 price 升序,返回前 10 条
q := redisearch.NewQuery("@price:[500 1000]").
SortBy("price", true).
Limit(0, 10)
docs, total, err := client.Search(q)
if err != nil {
panic(err)
}
fmt.Printf("匹配 %d 条,结果:%v\n", total, docs)
六、最佳实践
字段声明时加
SORTABLE
使SORTBY与范围过滤都能利用压缩索引,高效跳过不匹配文档。尽量在查询字符串中指定范围
直接使用@field:[a b],避免FILTER的后置过滤带来的额外扫描。分页与并发拉取
对于百万级以上结果集,避免一次性拉取所有结果,用LIMIT分页,并发执行多次查询或使用游标。监控查询性能
通过FT.INFO idx查看索引 cardinality、统计信息;用LATENCY命令监控查询延迟分布。结合其他索引类型
可将数值过滤与全文(TEXT)、标签(TAG)、地理(GEO)等条件组合,使用布尔子句优化多维度查询。
七、常见误区
- 误用通配符
*加 FILTERFT.SEARCH idx "*" FILTER price x y等价于全表扫描再过滤,性能逊于直接@price:[x y]。 - 忽略
SORTABLE
未加SORTABLE的数值字段无法在查询时高效排序或范围扫描。 - 忘记 LIMIT
默认只返回前 10 条,若需遍历后续结果,务必使用LIMIT offset count。
八、总结
Redis 数值范围查询提供了简洁灵活的语法和高效的执行性能。通过在索引设计阶段添加 NUMERIC SORTABLE,在查询时优先使用 @field:[a b],并结合 SORTBY 和 LIMIT,即可在大规模数据集上快速完成价格区间、阈值筛选等场景下的检索需求。配合监控与索引优化,你将获得更稳定、更低延迟的数值范围查询体验。
到此这篇关于Redis 数值范围查询(Numeric Range Queries)的实现的文章就介绍到这了,更多相关Redis 数值范围查询内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
