新闻详情

新闻详情

首页 / 资讯中心 / 详情

go-redis 实战:用 TS.QUERYLABELS 实现时序标签下钻查询(TSQueryLabels / TSQueryLabelValues)

发布时间:2026/10/1 9:30:17来源:尧图网络
go-redis 实战:用 TS.QUERYLABELS 实现时序标签下钻查询(TSQueryLabels / TSQueryLabelValues)
后端数据库客户端缓存【免费下载链接】go-redisRedis Go client项目地址https://gitcode.com/GitHub_Trending/go/go-redis点击查看免费下载导读本文围绕 go-redis 官方示例 example/ts-querylabels 展开系统讲解 Redis 8.10 TimeSeries 模块新增的TS.QUERYLABELS命令在 go-redis 中的两种绑定形式TSQueryLabels查询一组匹配时序上出现的全部标签名与TSQueryLabelValues查询某个标签在匹配时序上取到的全部值。读完本文你将掌握用 go-redis 构建标签名 → 标签值 → 时序键三级下钻drill-down流程的完整写法理解客户端如何构造命令参数、服务器返回语义有哪些边界行为并看懂对应的单元测试与集成测试如何钉死命令的线上格式wire format。背景标签发现为何重要RedisTimeSeries 中的每条时序time series都可以携带一组标签label例如{type: sensor, location: kitchen, unit: celsius}。标签是时序检索的核心索引TS.QUERYINDEX可以返回匹配某个过滤表达式的全部时序键TS.MRANGE/TS.MGET可以跨多组时序聚合查询。但在给用户一个查询界面的真实场景中用户并不预先知道系统里存在哪些标签、某个标签有哪些可选值。仪表盘工具如 Grafana需要在运行时动态填充下拉框变量variable dropdowns这就需要一个从粗到细逐级缩窄的流程先问这批匹配的时序上都有哪些标签名再问选中的某个标签在匹配时序上有哪些取值最后问完整筛选条件下具体是哪些时序键Redis 8.10 的TS.QUERYLABELS正好补齐了前两步与既有的TSQueryIndex一起构成完整的下钻闭环。go-redis 在 timeseries_commands.go 中为其提供了两个绑定方法并配套了官方示例与测试。命令的两种形式与 Go 绑定TS.QUERYLABELS有两种形式对应 go-redis 两个方法接口声明见 timeseries_commands.go命令形式go-redis 方法语义TS.QUERYLABELS LABELS [FILTER expr ...]TSQueryLabels(ctx, filterExpr)返回匹配时序上出现过的全部标签名集合TS.QUERYLABELS VALUES label [FILTER expr ...]TSQueryLabelValues(ctx, label, filterExpr)返回指定标签在匹配时序上取到的全部值集合两个方法都返回*StringSliceCmd即一组字符串服务器端返回的是无序、已去重的集合客户端不做额外排序或去重。过滤表达式的传递规则filterExpr使用的是与TSQueryIndex、TSMRange完全相同的过滤表达式语言如typesensor、location!kitchen、l(a,b)等并且原样透传verbatim给服务器客户端不做任何解析、校验或改写。这意味着传入nil或空切片[]string{}表示不附加任何过滤条件查询数据库内所有已建立索引的时序传入多个表达式时顺序原样保留由服务器端负责解释。空过滤器必须省略 FILTER 关键字一个容易踩坑的实现细节是当过滤表达式为空时客户端必须省略FILTER关键字因为服务器会拒绝一个光秃秃的FILTER。go-redis 通过内部辅助函数 appendTSFilter 处理这一点func appendTSFilter(args []interface{}, filterExpr []string) []interface{} { if len(filterExpr) 0 { return args } args append(args, FILTER) for _, f : range filterExpr { args append(args, f) } return args }运行示例三步下钻 两个边界场景官方示例位于 example/ts-querylabels/main.go演示了一个完整的仪表盘下钻流程。先创建 4 条带标签的时序作为种子数据series : map[string]map[string]string{ ts:temp:kitchen: {type: sensor, location: kitchen, unit: celsius}, ts:temp:bedroom: {type: sensor, location: bedroom, unit: celsius}, ts:hum:kitchen: {type: sensor, location: kitchen}, ts:build:count: {type: counter}, }注意ts:hum:kitchen故意没有unit标签ts:build:count只有type标签——它们正是用来演示边界行为的。第 1 步第一个下拉框——标签名labels, err : rdb.TSQueryLabels(ctx, []string{typesensor}).Result() fmt.Printf(label names for typesensor: %v\n, labels)过滤出所有typesensor的时序返回它们携带的标签名集合。示例输出label names for typesensor: [location type unit]两个关键点示例注释与源码注释一致返回无序且去重包含过滤条件本身用到的标签名这里就是type。第 2 步第二个下拉框——标签值locations, err : rdb.TSQueryLabelValues(ctx, location, []string{typesensor}).Result() fmt.Printf(locations for typesensor: %v\n, locations)在typesensor的时序组里查询location标签的所有取值。输出locations for typesensor: [bedroom kitchen]没有location标签的时序本组内不存在此情况但见第 3 步的unit对该集合不产生任何贡献。第 3 步第三个下拉框——时序键下钻到最终条件后用既有的TSQueryIndex拿具体时序键series, err : rdb.TSQueryIndex(ctx, []string{typesensor, locationkitchen}).Result() fmt.Printf(kitchen sensor series: %v\n, series)输出kitchen sensor series: [ts:hum:kitchen ts:temp:kitchen]至此标签名 → 标签值 → 时序键三级下钻完成。TSQueryIndex的实现见 timeseries_commands.go与TS.QUERYLABELS共用同一套过滤表达式语言。边界场景 A不存在的标签返回空集合而非错误missing, err : rdb.TSQueryLabelValues(ctx, rack, []string{typesensor}).Result() fmt.Printf(values of an absent label: %d\n, len(missing))没有任何匹配时序携带rack标签时返回空回复empty reply而不是错误输出0。这对仪表盘很关键某个标签值暂时为空时界面照常工作不会中断渲染。边界场景 B无过滤条件查询全部all, err : rdb.TSQueryLabels(ctx, nil).Result() fmt.Printf(label names, all series: %v\n, all)不传任何过滤器查询数据库内所有已建立索引的时序。示例输出label names, all series: [location type unit]注意这里没有rack等标签因为种子数据中根本不存在。运行方式与环境要求示例模块声明见 example/ts-querylabels/go.mod其中replace github.com/redis/go-redis/v9 ../..让示例直接指向仓库根目录的 go-redis 源码。运行前需要Redis 8.10并加载 TimeSeries 模块服务监听在localhost:6379代码中的redis.Options{Addr: localhost:6379}。进入示例目录后直接运行go run .预期输出集合内部顺序可能不同label names for typesensor: [location type unit] locations for typesensor: [bedroom kitchen] kitchen sensor series: [ts:hum:kitchen ts:temp:kitchen] values of an absent label: 0 label names, all series: [location type unit]示例代码在main开头先seed建时序、结束前rdb.Del(ctx, keys...)清理保证可重复运行。源码级剖析命令构造与线上格式两个方法的完整实现timeseries_commands.gofunc (c cmdable) TSQueryLabels(ctx context.Context, filterExpr []string) *StringSliceCmd { args : []interface{}{TS.QUERYLABELS, LABELS} args appendTSFilter(args, filterExpr) cmd : NewStringSliceCmd(ctx, args...) _ c(ctx, cmd) return cmd } func (c cmdable) TSQueryLabelValues(ctx context.Context, label string, filterExpr []string) *StringSliceCmd { args : []interface{}{TS.QUERYLABELS, VALUES, label} args appendTSFilter(args, filterExpr) cmd : NewStringSliceCmd(ctx, args...) _ c(ctx, cmd) return cmd }由此可以推断出实际发往服务器的参数序列调用生成的参数TSQueryLabels(ctx, nil)TS.QUERYLABELS LABELSTSQueryLabels(ctx, []string{typesensor})TS.QUERYLABELS LABELS FILTER typesensorTSQueryLabelValues(ctx, location, []string{typesensor})TS.QUERYLABELS VALUES location FILTER typesensorTSQueryLabelValues(ctx, location, nil)TS.QUERYLABELS VALUES location单元测试钉死 wire formattimeseries_querylabels_unit_test.go 中的TestTSQueryLabelsArgs用captureCmdable捕获命令参数逐条比对期望值重点验证了四件事FILTER令牌的省略规则nil与空切片都生成不带FILTER的参数labels_without_filter_omits_filter_token、labels_with_empty_filter_slice_omits_filter_token过滤器原样、有序传递[]string{typesensor, location!, l(a,b)}原样出现在参数中labels_filters_verbatim_and_orderedVALUES 形式同样遵循省略规则values_without_filter_omits_filter_token、values_with_filters标签名不做任何规范化TSQueryLabelValues(ctx, LoCaTiOn , nil)生成的参数就是TS.QUERYLABELS VALUES LoCaTiOn——前导与尾随空格、大小写原样保留values_label_not_normalized。最后这一点与集成测试中的字节精确匹配遥相呼应标签名按字节精确匹配Location与location是两个不同的标签。集成测试RESP2 / RESP3 下的行为验证timeseries_querylabels_integration_test.go 用 Ginkgo/Gomega 在 RESP2 与 RESP3 两种协议下各跑一遍通过SkipBeforeRedisVersion(8.10, ...)在低于 8.10 的服务器上自动跳过并用FlushDB 组内唯一过滤值test_groupquerylabels-test-respN隔离数据。它验证的行为与示例 README 的关键点一一对应标签名集合包含过滤条件中的标签名ConsistOf(test_group, location, unit)标签值集合去重、缺标签的时序不贡献location得到kitchen、bedroom两个值而只有部分时序携带的unit只得到celsius一个值不存在的标签返回空回复而非错误TSQueryLabelValues(ctx, no-such-label, ...)期望BeEmpty()标签名字节精确匹配查询Location大写变体得到空集合省略过滤器查询全部已索引时序在FlushDB后的空库中TSQueryLabels(ctx, nil)恰好返回本组三条时序的标签集合服务端过滤错误原样传播传一个只有非包含匹配test_group!...的过滤器时错误由服务器返回且包含TSDB:前缀——客户端不参与语法校验印证了过滤器原样透传的设计。这套测试同时覆盖了 RESP2 的数组回复与 RESP3 的集合回复说明两个方法在两种协议下的返回类型*StringSliceCmd都能正确解析。小结TS.QUERYLABELS是 Redis 8.10 TimeSeries 为仪表盘下钻场景补齐的关键拼图。go-redis 通过TSQueryLabels与TSQueryLabelValues两个方法封装了它的两种形式加上既有的TSQueryIndex可以构建出标签名 → 标签值 → 时序键的完整变量下钻流程。使用时要记住三点过滤器与TSQueryIndex/TSMRange共用同一套表达式语言并被原样透传回复是无序去重、包含过滤标签名的字符串集合标签缺失或查询无结果返回空回复而非错误因此仪表盘逻辑可以放心地把空当作合法的界面状态。想要深入验证行为可以阅读仓库中的 单元测试 与 集成测试想要直接跑起来观察输出参考 示例 README 与 main.go。赞分享后端数据库客户端缓存【免费下载链接】go-redisRedis Go client项目地址https://gitcode.com/GitHub_Trending/go/go-redis点击查看免费下载相关推荐告别混乱时序Grafana标签化注释查询实战指南告别混乱时序Grafana标签化注释查询实战指南 你是否还在为时间序列数据中的关键事件标记而烦恼当系统故障发生时能否快速定位到同时段的异常指标Grafa可观测性指标监控数据可视化告警日志分析后端前端Lightdash Data App drillDown() API 实战指南从点击行构建下钻查询Lightdash Data App drillDown API 实战指南从点击行构建下钻查询 drillDown 是 Lightdash Query SDK后端前端数据分析数据可视化人工智能AI AgentIT-Tools 加密解密实战HMAC 生成、JWT 解析与 RSA 密钥三个场景讲明白IT Tools 加密解密实战HMAC 生成、JWT 解析与 RSA 密钥三个场景讲明白 接口签名死活对不上却不知道是明文、密钥还是编码的问题拿到一串 J开发工具前端上一篇BootstrapCDN by jsDelivr下一篇【亲测免费】 cron-parser: 解析Unix Cron表达式的强大工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

ATL71.DLL缺失的彻底修复:从原理到实操的完整指南 2026/10/2 3:02:52

ATL71.DLL缺失的彻底修复:从原理到实操的完整指南

我先问一句:你机器上是不是也蹦出过这么一句——“无法启动此程序,因为计算机中丢失ATL71.DLL。尝试重新安装该程序以解决此问题。”如果答案是肯定的,那你多半正对着一台装着老软件的Windows电脑。atl71.dll这个东西,平时安安静静…

阅读更多 →
SpringBoot+Vue考研互助平台:从零搭建到部署的完整毕设指南 2026/10/2 3:02:52

SpringBoot+Vue考研互助平台:从零搭建到部署的完整毕设指南

说句实话,现在很多做毕设的同学,拿到题目之后最容易卡住的地方不是写代码,而是不知道这个项目到底要做什么、做到什么程度算完整。我最近整理的这个SpringBootVue考研互助交流平台管理平台,就是一个拿来就能跑、跑起来就有得讲的完…

阅读更多 →
Android Studio统计Java代码总行数:Find in Path+正则一招搞定 2026/10/2 3:02:52

Android Studio统计Java代码总行数:Find in Path+正则一招搞定

开头我先把话说清楚:这篇文章解决的就是一个看似无关紧要、但真到用的时候能卡住人的问题——统计Android Studio项目里Java代码的总行数。标题里那几个关键字我都覆盖到:Android Studio、Java、代码总行数。不管你是要给领导汇报项目规模,还…

阅读更多 →
命令行文件管理实战:从通配符到批量重命名 2026/10/2 3:02:45

命令行文件管理实战:从通配符到批量重命名

1. 为什么要学会用文件名来管理文件用命令行管理文件,这件事听起来像上古时代的操作,但真到用的时候才知道有多爽。我做技术工作这些年,日常就是跟服务器、日志、代码仓库打交道,最早面对黑底白字的终端窗口时也很抗拒&#xff0c…

阅读更多 →
西门子S7-1200压装设备:从SCL状态机到压力位移曲线采集 2026/10/2 3:02:39

西门子S7-1200压装设备:从SCL状态机到压力位移曲线采集

做汽车零部件压装设备的同行应该都有这种经历:客户报过来的工艺卡上就一句话——“压装力合格范围201.5kN,最终位移12.50.2mm”,但到了验收阶段,一条完整的压力位移曲线却成了硬性指标。曲线稍微有点毛刺、台阶,人家就…

阅读更多 →
一行Docker命令跑通YOLOv8目标检测:CPU与GPU实战避坑指南 2026/10/2 3:02:39

一行Docker命令跑通YOLOv8目标检测:CPU与GPU实战避坑指南

如果你的电脑上恰好装过YOLOv8,大概能理解那种“配置环境两小时,跑通模型五分钟”的憋屈。Python版本不对、CUDA和cuDNN匹配不上、PyTorch编译的CUDA版本对不上显卡驱动——随便一个问题都能让人在深夜对着终端发呆。这次我用Docker把YOLOv8的目标检测服…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉