Bogie
Bogie

Reputation: 119

Mongoose how to update multiple subdocuments in different documents in one call - MERN stack

I want to make an API call via mongoose to update the date field of a batch of selected Players (schema below) cards subdocument to the current date.

The Player schema:

const playerSchema = new Schema({
  name: String,
  cards: [{
    date: { type: Date, required: true },
    note: String
  }],
});

I created a checkbox where a user can select multiple Players (along with a specific 'card' subdocument from their cards array) and change the dates to be the same for those specific cards for all the selected Players. In react, I batched the corresponding ObjectIds together in the body and am sending the selected player/card combos in an array of objects that look as follows (where the number indicates the same grouped player & card subdocument ObjectId):

The array that I am sending to the server (accessible via req.body.cards):

[ {cardId: card1._id, playerId: player1._id},
  {cardId: card2._id, playerId: player2._id},
  {cardId: card3._id, playerId: player3._id} ]

In my Node/Express server put route, how would I go about updating all of those players and their specific card and giving them all the same date (Date.now()) asynchronously? In other words, how would I properly iterate over all the different playerIds and their respective cardId (preferably without any external libraries)?

Here's how I am updating a single card for a single player in my regular put route for editing the cards subdocument:

Player.findById(playerId)
  .then(player => {
    const card = player.cards.id(cardId);
    card.date = Date.now();

    player.save(
      (err, updatedCard) =>
        err
          ? console.log("Error in update card: " + err)
          : res.send(updatedCard)
    );
  })
  .catch(err => res.status(404).json({ success: false }));

Upvotes: 1

Views: 548

Answers (1)

cEeNiKc
cEeNiKc

Reputation: 1318

I think this should work.

Single player can be updated with this query:-

Player.findOneAndUpdate(
  { _id: playerId, "cards._id": cardId },
  { $set: { "cards.$.date": Date.now() } }
);

Multiple players can be updated with this query

Player.update(
  { $or: [{ _id: player1Id, "cards._id": card1Id }, { _id: player2Id, "cards._id": card2Id }, { _id: player3Id, "cards._id": card3Id }] },
  { $set: { "cards.$.date": Date.now() } },
  { multi: true }
);

Positional operator $ will take care of updating the correct card inside the array with the given card Id.

Upvotes: 1

Related Questions