如何通过GraphQL获取新建子文档的ID?
解决方案:高效获取打卡新建子文档ID并优化打卡流程
方法1:服务端预生成子文档ID(推荐,避免并发问题)
通过手动生成hoursWorked子文档的ID,直接返回给客户端,无需从整个数组中检索。
修改服务端Resolver(clockIn)
const mongoose = require('mongoose'); // 确保已引入mongoose clockIn: async (parent, args, context) => { if (context.user) { // 预生成子文档ID const newWorkHourId = new mongoose.Types.ObjectId(); const updatedUser = await User.findOneAndUpdate( {_id: context.user._id }, { clockedIn: true, $push: { hoursWorked: { _id: newWorkHourId, // 注入预生成的ID clockedInTime: args.clockedInTime, forDate: new Date(parseInt(args.clockedInTime)).toDateString() }, }, }, {new: true} ) .select('-__v -password') return updatedUser; } throw new AuthenticationError('You must be Logged In') },
客户端修改handleClockIn
直接从返回的hoursWorked数组末尾取新生成的ID:
const handleClockIn = async (dbInTime) => { try { const response = await sendClockIn({ variables: { clockedInTime: dbInTime.getTime().toString() } }); const hoursList = response.data.clockIn.hoursWorked; setCurrentClockedInId(hoursList[hoursList.length - 1]._id); } catch (e) { console.error(e) } }
如果想进一步简化客户端逻辑,可以修改Schema让clockIn直接返回新建ID:
服务端Schema修改
type ClockInResult { user: User newWorkHourId: ID! } type Mutation { clockIn(clockedInTime: String!): ClockInResult clockOut(clockedId: String!, clockedOutTime: String!): User }
服务端Resolver修改
clockIn: async (parent, args, context) => { if (context.user) { const newWorkHourId = new mongoose.Types.ObjectId(); const updatedUser = await User.findOneAndUpdate( {_id: context.user._id }, { clockedIn: true, $push: { hoursWorked: { _id: newWorkHourId, clockedInTime: args.clockedInTime, forDate: new Date(parseInt(args.clockedInTime)).toDateString() }, }, }, {new: true} ) .select('-__v -password') return { user: updatedUser, newWorkHourId: newWorkHourId.toString() }; } throw new AuthenticationError('You must be Logged In') },
客户端GraphQL突变修改
export const CLOCK_IN = gql` mutation clockIn($clockedInTime: String!) { clockIn(clockedInTime: $clockedInTime) { newWorkHourId user { _id clockedIn } } } `;
客户端handleClockIn简化
const handleClockIn = async (dbInTime) => { try { const response = await sendClockIn({ variables: { clockedInTime: dbInTime.getTime().toString() } }); setCurrentClockedInId(response.data.clockIn.newWorkHourId); } catch (e) { console.error(e) } }
方法2:直接从返回数组取最新ID(无需修改Schema)
利用MongoDB$push操作会将新元素追加到数组末尾的特性,客户端直接取最后一个元素的ID:
const handleClockIn = async (dbInTime) => { try { const response = await sendClockIn({ variables: { clockedInTime: dbInTime.getTime().toString() } }); const { hoursWorked } = response.data.clockIn; setCurrentClockedInId(hoursWorked[hoursWorked.length - 1]._id); } catch (e) { console.error(e) } }
额外优化:合并clockOut的两次数据库操作
当前clockOut resolver执行了两次数据库查询,可合并为一次提升效率:
clockOut: async (parent, args, context) => { if (context.user) { const updatedUser = await User.findOneAndUpdate( { _id: context.user._id, "hoursWorked._id": args.clockedId }, { clockedIn: false, "hoursWorked.$.clockedOutTime": args.clockedOutTime }, { new: true } ) .select('-__v -password') return updatedUser; } throw new AuthenticationError('You must be Logged In') },
内容的提问来源于stack exchange,提问作者UltimaDJS
相关产品推荐
相关产品推荐

