MongoDB聚合使用$size后匹配报错:传入$size的参数为字符串而非数组
问题原因分析
报错根本原因
- 你对
$size操作符的用法有误:$size的参数应该直接是目标数组字段,正确写法是{$size: "$language"},你额外套了一层数组{$size: ["$language"]},本质是计算你手动创建的新数组的长度,只要$language字段存在,返回值永远为1,根本不是你要的「语言数组元素数量」,之前的运行结果是完全错误的。 - 集合中存在部分文档的
language或ethnic_group字段是字符串类型,而非数组类型。MongoDB的聚合管道存在优化逻辑,会将$match阶段的条件下推到$project之前执行,减少需要处理的数据量。优化后的管道会直接对原始字段执行$size计算,此时遇到字符串类型的字段就会触发你看到的类型错误。
解决方法
先判断字段类型,对非数组类型做兼容处理后再计算长度,参考代码如下:
db.country.aggregate([ { $project: { _id: 0, name: 1, // 兼容数组、字符串、空值三种情况 size_of_language: { $cond: [ { $isArray: "$language" }, { $size: "$language" }, // 非数组场景:字段存在且非空算1个,不存在/为空算0个 { $cond: [ { $ne: [ "$language", null ] }, 1, 0 ] } ] }, size_of_ethnic: { $cond: [ { $isArray: "$ethnic_group" }, { $size: "$ethnic_group" }, { $cond: [ { $ne: [ "$ethnic_group", null ] }, 1, 0 ] } ] } } }, { $match: { $expr: { $eq: [ "$size_of_language", "$size_of_ethnic" ] } } } ])
如果你的业务规则里单语言/单族群的场景应该存为数组,建议先对全量数据做清洗,将language和ethnic_group字段统一为数组类型,后续就不需要额外做兼容判断。
内容的提问来源于stack exchange,提问作者William.Lee
相关产品推荐
相关产品推荐

