在使用FT.AGGREGATE聚合数据时,如何在Redis上解析ISO 8601时间?

gmxoilav  于 12个月前  发布在  Redis
关注(0)|答案(1)|浏览(128)

我有一个数据库,其中的key以ISO 8601格式存储UTC时间,如下所示:

(data:key1)
{ "time": "2023-12-10T10:42:50.277Z" }
(data:key2)
{ "time": "2023-12-15T19:02:40.308Z" }
...

字符串
我想以某种方式聚合这些键中的数据,比方说我想计算时间在2023-12-10和2023-12-29之间的键的数量。
Redis在其RediSearch模块中包含了FT.AGGREGATE命令,以及一个APPLY子命令,该子命令可用于使用不同类型的表达式转换数据。要将基于字符串的时间转换为数值,文档中列出的两个转换似乎不错:

**timefmt(x, [fmt])根据数字时间戳值x返回格式化的时间字符串。有关格式化选项,请参阅strftime。不指定fmt相当于%FT%TZ。parsetime(timesharing, [fmt])**与timefmt()相反-使用给定的格式字符串解析时间格式

然而,我找不到一种方法来实现这一点。我首先用FT.CREATE mySearch ON JSON PREFIX 1 data: SCHEMA $.time AS time TEXT创建一个搜索索引,然后调用FT.AGGREGATE mySearch "*" APPLY "parsetime(@time, '%G-%m-%dT%H:%M:%S.%fZ')" as numericTime进行聚合,响应是:

1) "1"
2) 1) "time"
   2) "2023-12-14T20:42:50.277Z"
   3) "numericTime"
   4) "null" // <- this should be a unix timestamp instead of null


我做错了什么,以及将这些时间字符串解析为数值的正确方法是什么?

axkjgtzd

axkjgtzd1#

我花了20分钟来观察Redis如何响应包含日期和时间的各种字符串。

  • 搜索将返回null,如果你给予它的格式选项是无效的。我尝试了它与%q,这是非常无效的,以确认这一点。
  • Redis的Search文档指向strftime的Python文档。这是不正确的,需要纠正(我会向我们的文档团队指出这一点)。Search不是在Python中实现的,而是在C中实现的。所以,它实际上使用了C formatting options,这略有不同。
  • C格式规范不支持%f的微秒格式,而Python格式规范支持。事实上,它根本不支持秒的分数。所以,这是行不通的。
  • 此外,你的字符串中有 * 毫秒 *,而不是微秒。所以,即使搜索使用Python规范,它仍然是不正确的。Python可能足够聪明,可以解决这个问题,但我没有测试,因为它没有实际意义。

在我看来,你有两个选择:

*如果毫秒很重要,你可以在将其保存到Redis之前将其转换为UNIX Epoch时间。搜索将很乐意处理包含小数的数字。亲自完成。完全有效。只要确保将其保存为JSON中的 number,而不是包含数字的字符串。
*如果毫秒不重要,在保存到Redis之前,请从ISO 8601日期中删除毫秒。

还有几件事值得注意:

  • 您的字符串中有一个错误。您使用%G表示年份。它应该是%Y%G是基于周的年份,而不是实际年份。ISO 8601日期使用实际年份。
  • 您可以使用一些快捷方式来解析此格式。%F%Y-%m-%d的缩写,%T%H:%M:%S的缩写。
  • 您可以使用%Z来匹配时区。这比使用硬编码的Z更健壮一些,因为您可能会遇到指定时区的时间。

所有这一切都表明,我可以修改你的解析字符串为%FT%T%Z,但我认为%Y-%m-%dT%H:%M:%S%Z可能更容易阅读。
无论如何,这是一个很长的回答,但我希望它能有所帮助!

相关问题