从MongoDB查询元素索引始终返回-1的问题求助
问题:Territory数组中查找当前元素索引始终返回-1
在Territory详情页实现「上一个/下一个」切换功能时,尝试在控制器中查找当前Territory在数组中的索引,结果始终返回-1,但用console.log输出数组时明明能看到目标元素存在。
当前控制器代码:
export const renderTerritoryHistory = (req, res, next) => { Territory .findById(req.params.territory_id) .populate(["preacher", "history"]) .exec() .then((territory) => { Territory .find({congregation: req.user._id}) .exec() .then((territories) => { console.log(territories); const currentIndex = territories.findIndex(t => t._id === mongoose.Types.ObjectId(territory._id)); console.log(currentIndex); res.render("./territories/show", { header: `Teren nr ${territory.number} | Territory Manager`, territory: territory, countDaysFromNow: countDaysFromNow, currentUser: req.user, currentIndex: currentIndex, territories: territories }) }) .catch((err) => console.log(err)) }) .catch((err) => console.log(err)) }
问题原因
核心问题是ObjectId的比较逻辑错误:
- Mongoose返回的
_id是ObjectId对象,不是普通字符串。直接用===比较两个ObjectId对象,哪怕它们的值完全相同,也会因为是不同的对象引用而返回false。 - 你额外把
territory._id转成新的mongoose.Types.ObjectId实例,这会生成一个全新的对象,和数组里的t._id引用完全不匹配,自然找不到索引。
解决方案
方案1:使用ObjectId的equals()方法(推荐)
Mongoose的ObjectId实例自带equals()方法,专门用来比较两个ObjectId的值是否相等:
const currentIndex = territories.findIndex(t => t._id.equals(territory._id));
方案2:转成字符串后比较
把两个ObjectId都转换成字符串再做相等判断:
const currentIndex = territories.findIndex(t => t._id.toString() === territory._id.toString());
方案3:优化查询逻辑(减少数据库请求)
可以合并两次查询,先获取所有符合条件的Territory,再从中定位当前项并填充关联数据,减少一次数据库调用:
export const renderTerritoryHistory = (req, res, next) => { Territory.find({ congregation: req.user._id }) .exec() .then((territories) => { // 先找到当前Territory const currentTerritory = territories.find(t => t._id.equals(req.params.territory_id)); if (!currentTerritory) { return res.status(404).send('Territory not found'); } // 填充关联数据 return currentTerritory.populate(["preacher", "history"]) .then(territory => { const currentIndex = territories.findIndex(t => t._id.equals(territory._id)); res.render("./territories/show", { header: `Teren nr ${territory.number} | Territory Manager`, territory: territory, countDaysFromNow: countDaysFromNow, currentUser: req.user, currentIndex: currentIndex, territories: territories }); }); }) .catch((err) => console.log(err)); };
内容的提问来源于stack exchange,提问作者Maciej Kuta
相关产品推荐
相关产品推荐

