使用$set聚合操作时MongoDB报'$concatArrays字段存储无效'问题排查
问题分析与解决方案
这是操作有误,并非MongoDB的bug,原因和正确写法如下:
核心问题
你在updateOne的$set中直接将聚合操作符$concatArrays作为字段值赋值,这种写法不符合MongoDB更新操作的规则:
- MongoDB的普通更新语法(非管道式)中,
$set等更新操作符的字段值只能是常量或特定的更新操作符(如$inc、$push),不支持直接使用聚合表达式。 - 4.4版本报错是因为它禁止存储键名以
$开头的字段($concatArrays作为对象键名属于非法存储字段),所以直接抛出错误。 - 5.0版本放宽了存储带
$字段名的限制,但依然没有将$concatArrays解析为聚合操作符,而是直接把整个对象当作普通值存入了values字段,这就是你看到文档被更新为包含聚合操作符对象的原因。
正确写法:使用管道式更新
从MongoDB 4.2开始,支持管道式更新——将更新内容用数组包裹,此时MongoDB会将里面的内容当作聚合管道的阶段处理,聚合操作符会被正确执行。
修正后的代码:
db.collection.updateOne( { _id: '65b26e3b9fd1100007f05d0b' }, [ { $set: { values: { $concatArrays: [ { $slice: ['$values', 1] }, { $slice: ['$values', { $add: [1, 1] }, { $size: '$values' }] } ] } } } ] );
执行效果
执行后,原始文档的values数组会被正确处理:原数组['0123456789', '']经过$slice取前1个元素,再拼接从索引2开始的空数组,最终values会变成['0123456789']。
内容的提问来源于stack exchange,提问作者Tofandel
相关产品推荐
相关产品推荐

