$slice在聚合中必须作为表达式使用,首参数须为数组字段路径(如"$fruits"),不支持字面量;正确语法为{ $slice: ["$arr", n] }或{ $slice: ["$arr", -n, m] },位置越界自动修正,空/null返回null需用$ifnull兜底。

$slice 在聚合管道中必须用作表达式,不能直接写在 project 字段值里当字面量用。它只接受数组表达式(如 "$fruits")作为第一个参数,不支持字符串字面量或硬编码数组。
聚合中 $slice 的语法必须带字段路径表达式
常见错误是写成 { $slice: ["apple", "banana", "orange", 2] } —— 这会报错 Expression $slice takes exactly 2 or 3 arguments,因为 $slice 在聚合阶段要求第一个参数是“能解析为数组的表达式”,比如 "$fruits" 或 { $ifNull: ["$tags", []] }。
- 正确写法:
{ $slice: ["$fruits", 2] }(取前两个)或{ $slice: ["$fruits", -3] }(取后三个) - 如果字段可能缺失或为
null,先兜底:{ $slice: [{ $ifNull: ["$fruits", []] }, 2] } - 不能省略引号:
"$fruits"是表达式,fruits或["apple",...]都不合法
位置+数量模式下 position 为负数时行为易混淆
写 { $slice: ["$fruits", -1, 2] } 并不是“从倒数第一个开始取 2 个”,而是“从数组末尾往前数 1 位作为起点,再向后取 2 个”——但数组末尾没有“向后”的空间,所以实际等价于 { $slice: ["$fruits", -1] },只返回最后一个元素。
-
{ $slice: ["$fruits", 1, 2] }:从索引 1 开始(第二个元素),取 2 个 →[fruits[1], fruits[2]] -
{ $slice: ["$fruits", -2, 1] }:从倒数第 2 个开始,取 1 个 → 就是倒数第 2 个元素 -
position超出范围不报错:若-10且数组只有 3 个元素,起点会被自动修正为 0
和 $push 更新里的 $slice 完全不是一回事
聚合里的 $slice 是纯计算操作符,只生成新数组;而更新语句里的 $slice 是修饰符,必须和 $each 搭配使用,作用是控制数组长度。两者名字相同、功能无关,混用会导致语法错误或逻辑错乱。
- 聚合中写
{ $push: { tags: { $slice: -5 } } }→ 报错:未知操作符$push在聚合 pipeline 阶段不可用 - 更新中写
{ $project: { latest: { $slice: ["$logs", -10] } } }→ 正确,这是聚合场景 - 更新中漏掉
$each:{ $push: { logs: { $slice: -10 } } }→ 报错The $slice modifier requires the $each modifier
真正容易被忽略的是:聚合中 $slice 对空数组或 null 字段返回 null(不是空数组),如果后续要用 $size 或 $map 处理,得提前用 $ifNull 转换,否则会中断 pipeline。











