简体   繁体   中英

How to update a MongoDB document field only once?

Hi there I'm trying to make a mongoose query to run only once if the field inside the document hasn't been updated already, but I'm getting a bit lost with the $exist , $update , $ne don't know what to use really.

I have the following query


const assignPhotoCodeToModel = (modelID, photoCode) => {
  const filter = { id: modelID }
  const update = { photoCode: photoCode }
  const options = { new: true, useFindAndModify: false }

  return new Promise((resolve, reject) => {

    ModelModel.findOneAndUpdate(filter, update, options)
      .then((response) => {
        resolve(response)
      })
      .catch((error) => {
        reject(error)
      })
  })
}

But I want this to run only if the field Model.photoCode is empty. If it already has a value I just want it to return that value.

The problem I'm having is that everytime the backend hits the route a new photoCode gets assign to the model even if it has been already assigned. So it gets reassign again again with a new one.

router.post(
  '/payment/success',
  (req, res, next) => {


 ...omitted_code...

                photoCodeModel
                .assignPhotoCodeToModel(req.body.modelId, photoCode)

... omitted_code

})

EDIT: 1:

Ok I'm writing this after trying the answers provided here. At first glance they seem to work, but now I'm getting into the error that when the Model.photoCode already has a value in it the return of the following function:

const assignPhotoCodeToModel = (modelID, photoCode) => {
  //the difference is here
  const filter = { id: modelID, photoCode : null }
  const update = { $set: { photoCode: photoCode } }

  const options = { new: true, useFindAndModify: false }

  return new Promise((resolve, reject) => {

    ModelModel.findOneAndUpdate(filter, update, options)
      .then((response) => {
        resolve(response)
      })
      .catch((error) => {
        reject(error)
      })
  })
}

returns null , while I'm actually expecting the same model document to be returned. I'm guessing is because of the filtering? When I remove the photoCode: null it goes back to "working", but then I'm back to the problem that photoCode field gets populated with new values

Basically I would like that function populates the filed photoCode once, but every subsequent call should just bring me back the same model document

I think what you need is $set . And, following your logic, I think you have to query "document that doesn't have photoCode yet". It should be:

const assignPhotoCodeToModel = (modelID, photoCode) => {
  //the difference is here
  const filter = { id: modelID, photoCode : null }
  const update = { $set: { photoCode: photoCode } }

  const options = { new: true, useFindAndModify: false }

  return new Promise((resolve, reject) => {

    ModelModel.findOneAndUpdate(filter, update, options)
      .then((response) => {
        resolve(response)
      })
      .catch((error) => {
        reject(error)
      })
  })
}

Write it in a neat asynchronous form. It will work.

const assignPhotoCodeToModel = async (modelID, photoCode) => {
  const filter = { id: modelID, photoCode : null };
  const update = { photoCode: photoCode };
  const options = { new: true, useFindAndModify: false };
  return await ModelModel.findOneAndUpdate(filter, update, options);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM