1

I want to update an object inside an array of schemas without having to do two requests to the database. I currently am incrementing the field using findOneAndUpdate() if the object already exists and it works fine. but in case the object does not exist then I am having to make another request using update() to push the new object and make it available for later increments.

I want to be able to do only one request (e.g. findOne()) to get the user and then increment the field only if object exists in the array and if not I would like to push the new object instead. then save the document. this way I am only making one read/request from the database instead of two.

this is the function now:

  async addItemToCart(body, userId) {
const itemInDb = await Model.findOneAndUpdate(
  {
    _id: userId,
    'cart.productId': body.productId,
  },
  { $inc: { 'cart.$.count': 1 } }
);
if (itemInDb) return true;

const updated = await Model.update(
  { _id: userId },
  { $push: { cart: body } }
);
if (updated.ok !== 1)
  return createError(500, 'something went wrong in userService');
return true;
}

what I would like to do is:

  async addItemToCart(body, userId) {
const itemInDb = await Model.findOne(
  {
    _id: userId,
    'cart.productId': body.productId,
  }
);
if (itemInDb) {
  /**
   * 
   * increment cart in itemInDb then do itemInDb.save()  <<------------
   */
} else {
  /**
   * push product to itemInDb then save
   */
}

Thank you!

2 Answers 2

2

You can try findOneAndUpdate with upsert.

upsert: true then create data if not exists in DB.

Model.findOneAndUpdate(
  {
    _id: userId,
    'cart.productId': body.productId,
  },
  { $inc: { 'cart.$.count': 1 } },
 {
     upsert: true,
   }
)

Use $set and $inc in one query.

try {
  db.scores.findOneAndUpdate(
    {
      _id: userId,
      'cart.productId': body.productId,
    },
     { $set: { "cart.$.productName" : "A.B.C", "cart.$.productPrice" : 5}, $inc : { "cart.$.count" : 1 } },
     { upsert:true, returnNewDocument : true }
  );
  }
  catch (e){
     //error
  }

reference Link : here

Sign up to request clarification or add additional context in comments.

2 Comments

The product in cart array has more fields than “count”, how do I add those if they object doesn’t exist?
it did not work because what I'm dealing with is an array of embedded sub documents. turns out to do it I would have to introduce a lot more complexity. check this answer: stackoverflow.com/a/49204544/9111239 . thank you for your effort!
0

You can use upsert.

upsert is defined as an operation that creates a new document when no document matches the query criteria and if matches then it updates the document. It is an option for the update command. If you execute a command like below it works as an update, if there is a document matching query, or as an insert with a document described by the update as an argument.

Example: I am just giving a simple example. You have to change it according to your requirement.

db.people.update(
   { name: "Andy" },
   {
      name: "Andy",
      rating: 1,
      score: 1
   },
   { upsert: true }
)

So in the above example, if the people with name Andy is found then the update operation will be performed. If not then it will create a new document.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.