$split后数组元素带空格因不自动去首尾空白,须用$map+$trim清洗;遇空字符串或重复分隔符会保留空元素,需$filler剔除;多级嵌套清洗应按split→trim→toLower→filter/setUnion顺序执行。

为什么 $split 后的数组元素还带空格?
因为 $split 只按分隔符切分,不处理首尾空白——哪怕源字符串是 " apple , banana , cherry ",$split 输出的仍是 [" apple ", " banana ", " cherry "]。直接 $map + $trim 是必须步骤,漏掉就等于白切。
实操建议:
- 永远在
$split后接$map,且内部用$trim处理每个元素,别试图用正则或$replace替代 -
$trim默认去空格,如需去其他字符(如换行、制表符),显式传入chars参数:{ input: "$$this", chars: " \t\n\r" } - 如果原始字段可能为
null或缺失,先用$ifNull或$cond做兜底,否则$split会报错TypeError: can't convert undefined to string
如何安全地处理多级嵌套的字符串数组?
常见场景:文档里存的是类似 "tag1;tag2; tag3 ; tag4" 的单字段,但业务要求最终输出为去重、去空、小写的标签数组。这时候不能只靠一层 $split,得串起清洗链。
实操建议:
- 顺序不能乱:先
$split→ 再$map+$trim→ 然后$map+$toLower→ 最后$setUnion或$filter去空/去重 - 用
$filter清空字符串比$setDifference更稳妥:{ input: "$cleanedTags", cond: { $ne: ["$$this", ""] } } - 避免在
$map中混用不同转换逻辑(比如一边 trim 一边 toLower),拆成两个独立$map阶段,可读性和调试性高得多
$split 对空字符串或重复分隔符怎么反应?
$split 遇到 "a,,b" 会产出 ["a", "", "b"],遇到 " "(纯空格)会产出 [""],不是 []。这点和 JavaScript 的 String.prototype.split() 行为一致,但容易被误判为“没切出东西”。
实操建议:
- 不要依赖
$size判断是否为空数组来跳过后续清洗——[""]的 size 是 1,但它本质是脏数据 - 清洗完成后务必加一步
$filter剔除空字符串,尤其当分隔符出现在头尾时(如",a,b,"→["", "a", "b", ""]) - 若源数据中存在非法分隔符(如用户误输中文逗号、全角分号),提前用
$replaceAll统一替换,再进$split,否则切出来全是碎片
性能与聚合阶段位置的关键细节
$split + $map 是 CPU 密集型操作,尤其在 $unwind 前执行,会显著拖慢整个 pipeline。更糟的是,如果把它放在 $group 后,可能因内存超限触发 errmsg: "Sort exceeded memory limit"。
实操建议:
- 尽可能把字符串清洗提前到
$project阶段,且在$match和$lookup之后、$unwind之前完成——既减少后续阶段处理量,又避免数组膨胀 - 如果字段值长度差异极大(比如有的长达 10KB,有的只有 3 字符),考虑加
$strLenCP判断后分支处理,防止大字符串拖垮小文档 - 在 Atlas 或 6.0+ 版本中,若清洗逻辑固定,可改用
$function封装复用,但注意沙箱限制:不能调用外部库,也不能递归
\u200b。这些不会被 $trim 干掉,得靠 $replaceAll 配合 Unicode 范围手动清。


















