使用Mongo ObjectId作为对象索引报错,寻求理想解决方法
问题:MongoDB ObjectId 作为对象索引类型报错的解决方法
我尝试遍历通过MongoDB的Model.find()方法获取的数组,编写了如下代码:
const lists = ListModel.find(); const listSet = lists.reduce<Record<string, Set<string>>>((acc, list) => { const listId = list._id; acc[listId] = new Set() return acc; }, {});
其中listId为new ObjectId(1234qwer1234qwer),运行时报错**"Type 'ObjectId' cannot be used as an index type."**。后续我还需要使用该ObjectId做引用,请问理想的处理方式是什么?
补充:曾尝试改用list.id替代list._id,但出现错误**"Type 'Buffer' cannot be used as an index type."**。
解决方案
核心原因
TypeScript中对象的索引类型仅支持string、number或symbol,而MongoDB的ObjectId(或Buffer)属于复杂类型,无法直接作为对象键名使用。
处理方法
1. 转字符串作为索引键,同时保留原ObjectId引用
将ObjectId转为字符串作为对象的键,同时在值中保留原ObjectId实例,方便后续直接使用:
// 注意:Mongoose的find()返回Query对象,需用await获取实际数组 const lists = await ListModel.find(); const listSet = lists.reduce<Record<string, { id: ObjectId; data: Set<string> }>>((acc, list) => { const listIdStr = list._id.toString(); acc[listIdStr] = { id: list._id, // 保留原ObjectId,后续直接引用 data: new Set() }; return acc; }, {}); // 后续使用示例: // 通过字符串键获取原ObjectId const targetObjectId = listSet['60d21b4667d0d8992e610c85'].id; // 通过已有ObjectId转字符串访问对应集合 const targetSet = listSet[someExistingObjectId.toString()];
2. 仅转字符串作为索引,后续按需转回ObjectId
如果不需要在对象中保留原ObjectId,可以直接用字符串作为键,后续需要用ObjectId做查询时,再将字符串转回ObjectId实例:
const lists = await ListModel.find(); const listSet = lists.reduce<Record<string, Set<string>>>((acc, list) => { const listIdStr = list._id.toString(); acc[listIdStr] = new Set(); return acc; }, {}); // 后续查询示例: const targetList = await ListModel.findById(new ObjectId('60d21b4667d0d8992e610c85'));
关于list.id报错的说明
list.id是Mongoose提供的便捷属性,通常会返回ObjectId的字符串形式,但如果你的Schema中_id类型不是默认的ObjectId(比如自定义了Buffer类型的_id),就会导致返回Buffer,同样无法作为索引类型。因此直接使用list._id.toString()是更可靠的方式。
内容的提问来源于stack exchange,提问作者Michael Koska
相关产品推荐
相关产品推荐

