先看现象。Milvus 2.4 加 pymilvus 2.4.4,created_at 是 INT64 毫秒时间戳,expr 写成 created_at > '2026-10-01',返回空列表而且不报错,改成数字才查到数据。

真正麻烦的地方在于,几个原因的现象几乎一样。INT64 字段与字符串比较,表达式被当成恒假。另一种情况是时间单位是毫秒,用秒级时间戳比较会差三个数量级。

另外,字段实际存的是 ISO 字符串,类型与 schema 不符。

少数情况下是查询前没有 load 集合,过滤在空段上执行。

动手时先确认字段类型与 schema

python -c "from pymilvus import Collection;print([(f.name,str(f.dtype)) for f in Collection('docs').schema.fields])"

再往下用毫秒数字过滤一次

python -c "from pymilvus import Collection;c=Collection('docs');c.load();print(c.query('created_at > 1759276800000',output_fields=['id']))"

然后对比总数排除空集合

python -c "from pymilvus import Collection;print(Collection('docs').num_entities)"

末了把时间字符串在应用层转成毫秒

python -c "from datetime import datetime;print(int(datetime(2026,10,1).timestamp()*1000))"

排查用的命令都是临时敲的,没有写成脚本,事后才整理。

改完先别撤,确认这几项。过滤后返回的条数与直接按时间范围统计一致,空结果不再出现。

容易忽略的是,Milvus 的表达式不做隐式类型转换,类型对不上时往往返回空而不是报错,先核对 schema 再写条件。监控比日志更早给出信号,事后回看经常能提前半小时发现异常。

作者 9823189