MongoDB ObjectId与字符串ID比较返回false问题排查
问题:MongoDB ObjectId与字符串ID比较结果为false的解决方法
我基于Node.js + MongoDB开发API,需要验证请求体中传入的字符串格式proposerId是否等于MongoDB查询返回的活动组织者ID(eventData.organizer._id是ObjectId类型)。日志显示两者ID值完全相同,但比较结果始终为false。
请求体内容
{ "participantId": "6238a608170aff10d16ccd89", "proposerId": "62385d8caee17d13a1762b39", // this guy id is also an organizer "gender": "female", "groupId": "623aea21fcfad83bcf8d5bc4" }
控制器验证代码
exports.addParticipantToEvent = async (req, res, next) => { // Group Organizer constants const eventId = req.params.eventId; const groupId = req.body.groupId; const proposerId = req.body.proposerId; // it can be an admin adding someone to the participants list // Participant constants const participantId = req.body.participantId; const gender = req.body.gender; // EVENT // Does the event even exist? const eventData = await Event.findById(eventId); if (!eventData) { return res.status(406).json({ code: 'EVENT_DOESNT_EXIST', message: 'The event is not valid.', }); } console.log(eventData); // What kind of users can participate in this event? const allowedParticipants = eventData.allowedParticipants; // whos the event organizer? const eventOrganizer = eventData.organizer._id; console.log('Organizer: ' + eventOrganizer); console.log('Proposer: ' + proposerId); console.log('Result: ' + proposerId === eventOrganizer); try { return res.status(200).json({ message: 'The participant can be added', participantId: participantId, gender: gender, allowedParticipants: allowedParticipants, }); } catch (err) { return res.status(400).json({ message: err }); } };
日志输出
{ location: { province: 'Barcelona' }, _id: new ObjectId("634ffee75990124926431e6f"), title: 'Test open close 14', sport: new ObjectId("622ce6ca672c3d4447676705"), group: new ObjectId("623aea21fcfad83bcf8d5bc4"), organizer: new ObjectId("62385d8caee17d13a1762b39"), participants: [ new ObjectId("62385d8caee17d13a1762b39") ], replacements: [], invitations: [], when: 2022-10-09T13:43:02.999Z, open: true, costPerParticipant: 4.4, skill: 'novice', allowedGender: 'female', minParticipants: 2, maxParticipants: 5, visible: false, externalLink: 'https://www.komoot.es/tour/731122050?ref=wta', allowInvitations: true, allowReplacements: false, allowedParticipants: 'only-members', createdAt: 2022-10-19T13:43:03.006Z, updatedAt: 2022-10-19T13:43:03.006Z, __v: 0 } Organizer: 62385d8caee17d13a1762b39 Proposer: 62385d8caee17d13a1762b39 false
解决方法
1. 修正运算符优先级问题
当前代码中console.log('Result: ' + proposerId === eventOrganizer)存在优先级错误:字符串拼接+的优先级高于全等运算符===,实际执行的是('Result: ' + proposerId) === eventOrganizer,必然返回false。必须给比较表达式加括号:
console.log('Result: ' + (proposerId === eventOrganizer.toString()));
2. 转换ObjectId为字符串后比较
将MongoDB返回的ObjectId通过toString()方法转为字符串,再和请求体的字符串ID比较:
const isMatch = proposerId === eventOrganizer.toString(); console.log('Result: ' + isMatch);
3. 使用ObjectId自带的equals()方法
MongoDB的ObjectId实例提供了equals()方法,可直接接收字符串或另一个ObjectId进行匹配判断:
const isMatch = eventOrganizer.equals(proposerId); console.log('Result: ' + isMatch);
4. 查询时直接获取字符串ID(优化方案)
如果后续不需要使用ObjectId类型,可以在查询时使用.lean()返回普通JS对象,此时_id会自动转为字符串:
const eventData = await Event.findById(eventId).lean(); const eventOrganizer = eventData.organizer._id; // 此时已为字符串类型 const isMatch = proposerId === eventOrganizer;
内容的提问来源于stack exchange,提问作者Minide
相关产品推荐
相关产品推荐

