2

I'm executing an upsert mutation on MongoDB to create a new document or update an existing document. If the document exists, the mutation returns the id as expected. If a new document is created, the mutation returns null (in both Apollo sandbox and via console.log) in the initial return then in subsequent returns it will return the id. I need it to return the id of the newly created document immediately (on the first return) so I can use that id in subsequent actions.

Starting from the beginning here's the setup:

TYPEDEF

updateHourByEmployeeIdByJobDate(
      jobDate: String
      startTime: String
      endTime: String
      hoursWorked: String
      employee: String
    ): Hour

RESOLVER

updateHourByEmployeeIdByJobDate: async (
      parent,
      { jobDate, startTime, endTime, hoursWorked, employee },
      context
    ) => {
      // if (context.user) {
      console.log("resolver hours update = ");
      return Hour.findOneAndUpdate(
        { employee, jobDate },
        {
          jobDate,
          startTime,
          endTime,
          hoursWorked,
          employee,
        },
        {
          upsert: true,
        }
      );
      // }
      // throw new AuthenticationError("You need to be logged in!");
    },

MUTATION

//UPDATE HOUR RECORD - CREATES DOCUMENT IF IT DOESN'T EXIST OR UPDATES IF IT DOES EXIST VIA THE UPSERT OPTION ON THE RESOLVER

export const UPDATE_HOURS_BYEMPLOYEEID_BYJOBDATE = gql`
  mutation UpdateHourByEmployeeIdByJobDate(
    $jobDate: String
    $startTime: String
    $endTime: String
    $hoursWorked: String
    $employee: String
  ) {
    updateHourByEmployeeIdByJobDate(
      jobDate: $jobDate
      startTime: $startTime
      endTime: $endTime
      hoursWorked: $hoursWorked
      employee: $employee
    ) {
      _id
    }
  }
`;

FRONT-END EXECUTION

const [ mostRecentHourUpdateId, setMostRecentHoursUpdateId ] = useState();

  const [updateHours] = useMutation(UPDATE_HOURS_BYEMPLOYEEID_BYJOBDATE, {
    onCompleted: (data) => {
      console.log('mutation result #1 = ', data)
      setMostRecentHoursUpdateId(data?.updateHourByEmployeeIdByJobDate?._id);
      console.log('mutation result #2 = ', mostRecentHourUpdateId)
    },
  });

  //section update database - this mutation is an upsert...it either updates or creates a record
  const handleUpdateDatabase = async (data) => {
    console.log(data);
    
    try {
      // eslint-disable-next-line
      const { data2 } = await updateHours({
        variables: {
          jobDate: moment(data.date).format("MMMM DD YYYY"), //"January 20 2023"
          startTime: `${data.startTime}:00 (MST)`, //"12:00:00 (MST)"
          endTime: `${data.endTime}:00 (MST)`, //"13:00:00 (MST)"
          hoursWorked: data.hours.toString(), //"3.0"
          employee: userId, //"6398fb54494aa98f85992da3"
        },
      });

      console.log('handle update database function = data = ', data2); //fix

    } catch (err) {
      console.error(err);
    }

    singleHoursRefetch();

  };

I've tried using onComplete as part of the mutation request as well as useEffect not to mention running the mutation in Apollo Sandbox. Same result in all scenarios. The alternative is to re-run the useQuery to get the most recent / last record created but this seems like a challenging solution (if at some point the records are sorted differently) and/or seems like I should be able to get access to the newly created record immediately as part of the mutation results.

Calla
  • 21
  • 3

1 Answers1

0

You'll want to use { returnNewDocument: true }

Like this:

const getData = async () => {
    const returnedRecord = await Hour.findOneAndUpdate( { employee, jobDate }, { jobDate, startTime, endTime, hoursWorked, employee, }, { upsert: true, returnNewDocument: true } );
    // do something with returnedRecord
}

getData();

For more information: https://www.mongodb.com/docs/manual/reference/method/db.collection.findOneAndUpdate/

Stephen Taylor
  • 798
  • 7
  • 19
  • 1
    Looks like that solves the issue. I'm familiar with that approach but just didn't occur to me. Thanks for the quick response! – Calla Jan 30 '23 at 21:09
  • Here's another post on the same issue (now that I know the solution). https://stackoverflow.com/questions/32811510/mongoose-findoneandupdate-doesnt-return-updated-document – Calla Jan 30 '23 at 23:05