Search code examples
node.jsmongodbmongoosemongoose-schema

how to save document and update another which are dependent on each other with mongoose


Here is my bid model.

const BidSchema = new Schema({
  auctionKey: {
    type: mongoose.Types.ObjectId,
    ref: "Auction",
    required: true
  },
  amount: { type: String, required: true },
  userName: { type: String, required: true },
});

And, here is my Auction Model (Notice the relationships between these two models).

const AuctionSchema = new Schema({
  title: { type: String, required: true },
  startDate: { type: Date, required: true },
  closeDate: { type: Date, required: true },
  initialBidAmount: { type: Number, required: true },
  bidIncrementAmount: { type: Number, required: true },
  bids: [
    {
      type: mongoose.Types.ObjectId,
      ref: 'Bid'
    }
  ]
});

When user bids for any auction, I'm saving bid in bids collection and updating auctions collection using mongoose findOneAndUpdate.

const postBid = async (req, res, next) => {
  const { auctionKey } = req.body;
  const bid = new BidModel(req.body);
  bid.save(error => {
    if (error) {
      res.status(500).json({ message: "Could not post bid." });
    }
  });

  const aucById = await AuctionModel.findOneAndUpdate(
    { _id: auctionKey },
    { $push: { bids: bid } }
  ).exec((error: any, auction: IAuction) => {
    if (error) {
      res.status(500).json({ message: "Could not post bid." });
    } else {
      res.status(201).json({ bid });
    }
  });
};

For any reason if any of these two (save bid and findOneAndUpdate) throws any error I want nothing to be saved into database. I mean to say either they should save and update or nothing should be done on database.

I have tried using mongoose session and transaction but got this error.

 MongoError: This MongoDB deployment does not support retryable writes. Please add retryWrites=false to your connection string.

Is there any way to work out in this scenario?


Solution

  • If I understand your problem right, you can just delete created document in:

    .exec((error: any, auction: IAuction) => {
        if (error) {
           // here, by using .deleteOne()
          res.status(500).json({ message: "Could not post bid." });
        }
    

    Or just change structure of your code, so only when two are successfully created, they will be saved and response will be sent.