You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 13:15:51