$sortByCount不能直接统计字符串数组中每个标签,因为它仅接受单个字段路径,会将整个数组视为一个值计数;必须先用$unwind拆解数组,再配合$match过滤空值、$toLower统一大小写,否则无法准确获取高频标签。
因为 $sortByCount 只接受单个字段路径(如 "$tags"),而如果 tags 是字符串数组(比如 ["mongodb", "nodejs", "react"]),它会把整个数组当做一个值来计数,结果就是“数组去重计数”,不是你想要的“每个标签单独计数”。
这是最常见也最容易漏掉的一步。不 $unwind,$sortByCount 就没法看到数组里的单个元素。
$unwind 要作用在数组字段上,比如 { $unwind: "$tags" }
preserveNullAndEmptyArrays: true 避免丢文档(但此时空值也会被计入,需后续 $match 过滤)$sortByCount: "$tags" —— 注意这里路径指向的是“拆开后的单个标签值”,不是原数组完整管道示例:
{ $unwind: "$tags" }{ $sortByCount: "$tags" }{ $limit: 10 }
真实数据里常混着无效标签:空字符串、纯空格、null。它们会被 $sortByCount 当作独立值统计,挤占前 10 名位置。
$unwind 后加 { $match: { tags: { $ne: null, $ne: "", $regex: "^S+$" } } } 过滤掉空值和空白字符串$toLower 统一格式:{ $addFields: { tags: { $toLower: "$tags" } } }
$toLower 不能直接用于 $sortByCount 的表达式里,必须提前转换字段值如果集合有百万级文档,且平均每个文档有 5–10 个标签,$unwind 会瞬间膨胀出几百万中间文档,可能触发内存限制(100MB 默认)。
$match 尽早缩小输入范围,比如只统计最近 30 天的数据tags 字段上有索引没用——$unwind 不走索引,但前置 $match 可以用allowDiskUse: true 让聚合落盘,但会变慢真正卡住的时候,往往不是语法错,而是忘了数据规模和中间态膨胀这回事。