MongoDB聚合查询报错pipeline[(pipeline.length - 1)] is undefined
MongoDB聚合报错:pipeline[(pipeline.length - 1)] is undefined
错误信息
动态运行聚合查询时抛出如下异常:
TypeError: pipeline[(pipeline.length - 1)] is undefined :
触发代码
var a = { "aggregate" : "income", "pipeline" : [ {$match:{sal : {$gt : 10000}}},{ "$skip" : 0}, { "$limit" : 5000 }], "cursor" : { "batchSize" : 5000 } }; if(a["aggregate"] != undefined) { var collectionName = a["aggregate"]; var query = a["pipeline"]; print(query) for(var k = 0;k<query.length;k++) { var b = query[k] if(b["$skip"] != undefined) { delete query[k]; } if(b["$limit"] != undefined) { delete query[k]; } } print(query) db.getCollection(collectionName).aggregate(query) }
根因分析
JavaScript数组使用delete操作符删除指定索引元素时,不会缩短数组长度、也不会移除索引占位,仅会将对应索引位置的值置为undefined。
上述代码执行删除逻辑后,pipeline数组实际结构为[ {$match:{sal:{$gt:10000}}}, undefined, undefined ],数组长度仍为3。将包含undefined元素的数组传入aggregate()方法后,MongoDB驱动读取管道最后一位元素时取到undefined,直接触发类型错误。
修复方法
不要使用delete操作符移除数组元素,选择下列任意一种方案修改即可:
- 方案1:使用
filter生成新的合法管道数组(推荐,逻辑简洁无索引副作用)
var a = { "aggregate" : "income", "pipeline" : [ {$match:{sal : {$gt : 10000}}},{ "$skip" : 0}, { "$limit" : 5000 }], "cursor" : { "batchSize" : 5000 } }; if(a["aggregate"] != undefined) { var collectionName = a["aggregate"]; // 过滤掉$skip、$limit阶段 var query = a["pipeline"].filter(stage => { return !Object.prototype.hasOwnProperty.call(stage, "$skip") && !Object.prototype.hasOwnProperty.call(stage, "$limit"); }); db.getCollection(collectionName).aggregate(query); }
- 方案2:原地修改数组时使用
splice方法删除元素,注意同步修正遍历索引
var query = a["pipeline"]; for(var k = 0; k < query.length; k++) { var b = query[k] if(b["$skip"] != undefined || b["$limit"] != undefined) { // 从当前索引位删除1个元素 query.splice(k, 1); // 数组长度缩短1,索引回退避免跳过相邻元素判断 k--; } }
注意:
delete仅适用于删除对象的自有属性,处理数组元素移除场景时,请使用splice、filter、slice等会正确维护数组索引和长度的原生方法。
内容的提问来源于stack exchange,提问作者chiku
相关产品推荐
相关产品推荐

