这个坑值得记一笔。collection 按 tenant_id 设了 partition_key,insert 一切正常,search 时只给向量和 topK,报 failed to create query plan: cannot parse expression,服务端是 Milvus 2.4.6 单机 docker。

刚开始盯着「SDK 版本 2.3 不认识 partition_key 元数据,生成不出对应过滤条件」,折腾了半个多小时,排掉了。

真正麻烦的地方在于,几个原因的现象几乎一样。设了 partition_key 的集合必须在过滤表达式里带该字段的等值条件;表达式写成 tenant_id in […],规划器要求等值而不是集合匹配;字段名大小写与 schema 不一致,解析阶段找不到这一列。

上来先打印集合 schema 确认分区键字段名

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

随后查询时补上分区键的等值过滤

python -c "from pymilvus import Collection;print(Collection('kb').search([[0.1]*8],'emb',{'metric_type':'COSINE'},limit=5,expr='tenant_id == \"t42\"'))"

再往下把 SDK 升到与 2.4 匹配的版本

pip install -U "pymilvus>=2.4.4"

批量脚本按分区键逐个查,避免空表达式

python -c "from pymilvus import Collection;c=Collection('kb');[c.search([[0.1]*8],'emb',{'metric_type':'COSINE'},limit=5,expr=f'tenant_id == \"{t}\"') for t in ['t42','t43']]"

别只看报错消失,验证要多做一步。查询返回 5 条命中且每条 payload 里的 tenant_id 都是 t42,服务端日志不再出现 cannot parse expression。

补一句。partition_key 每个集合只能设一个字段,也不能与主键同列,换租户模型时基本等于重建 collection。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。

作者 9823189