Why my document is not updating in mongoDB

53 views Asked by At

When attempting to update a nested array field within a MongoDB document using Mongoose's findOneAndUpdate method, I'm encountering a perplexing issue where the update doesn't seem to reflect in the database.

Here's a concise summary of the problem:

I have a MongoDB schema called Screen that includes an array field named timeslots. Within each timeslot, there's a nested array called seats, representing available seats in a cinema. I'm trying to update the status field of a specific seat to indicate it has been booked. Despite successfully modifying the status field locally, the update doesn't persist in the database.

Below is a snippet of my code:

router.post('/bookTicket', async (req, res) => {
    try {
        console.log("Book ticket API is triggered");

        // Find the screen details
        let getDetails = await Screen.findOne({ title: "DemonSlaye" }).lean()
        if (!getDetails) {
            return res.status(404).send("Screen not found");
        }

        console.log("Screen details before update:", getDetails);

        // Find the seat status and update it
        const foundSeat = getDetails.timeslots[0].seats
        .filter(seatTypeIterate => seatTypeIterate.type === 'platinum')
        .map(silverSeatRows => silverSeatRows.rows)
        .flat()
        .find(getrow => getrow.rowname === 'H')
        .cols[0]
        .seats
        .find(getSeatId => getSeatId.seat_id === '2');
        
        if (!foundSeat) {
            console.log("Seat not found");
            return res.status(404).send("Seat not found");
        }

        console.log("Seat status before update:", foundSeat);

        foundSeat.status = "booked";
        foundSeat.bookedBy = "userID";

        console.log("Updated seat status:", foundSeat);

        const hydratedDetails = Screen.hydrate(getDetails);
        console.log("Updating document with ID:", getDetails._id);
        // Replace the entire JSON document in the database with the updated one

        const updatedDocument=await hydratedDetails.save()
        console.log("Document updated successfully:", updatedDocument);

        res.send(updatedDocument)

        // res.send(hydratedDetails); // Sending the updated document as response
    } catch (error) {
        console.error("Error occurred:", error);
        res.status(500).send("An error occurred while booking the ticket.");
    }
});

Schema:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;


const screenSchema = new mongoose.Schema({
    status: { type: String},
    seat_id: { type: String},
    bookedBy: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }
});


const rowSchema = new mongoose.Schema({
    rowname: { type: String, required: true },
    cols: [screenSchema] // Array of seats
});


const timeslotSchema = new mongoose.Schema({
    seats: [{
        type: { type: String, required: true },
        rows: [rowSchema], // Array of rows
        price: { type: Number, required: true }
    }]
});



const movieSchema = new mongoose.Schema({
    title: { type: String, required: true },
    theatreId: { type: String, required: true },
    location: { type: String, required: true },
    language: { type: String, required: true },
    time: { type: String, required: true },
    screenType: { type: String, required: true },
    screenName: { type: String, required: true },
    timeslots: [timeslotSchema] // Array of timeslots
},
{ strict: false }
);



const Screen = mongoose.model('Screen', screenSchema);

module.exports = Screen;

Output: I attached the DB image , which has no updation of seat-staus: booked (seat_id:2)

I tried out using $set operator it doesnot work

My issue lies in attempting to update the nested array fields within a MongoDB document by modifying the document retrieved using findOne and then saving it back to the database using Mongoose's save method. While this approach may seem intuitive, it can lead to unexpected behavior because Mongoose's save method may not update nested arrays as expected. Instead, you should use Mongoose's findOneAndUpdate method, which is designed to update documents directly in the database and can handle nested arrays more effectively.

1

There are 1 answers

0
jQueeny On

The mongoose Model.hydrate() does not work the way you think.

When you do:

const hydratedDetails = Screen.hydrate(getDetails);

and then

const updatedDocument = await hydratedDetails.save();

It is the same Document. Nothing has changed from when you hydrated it so nothing is saved.

You need to make the changes after you do the hydration. So something like:

const hydratedDetails = Screen.hydrate(getDetails);
hydratedDetails.title = 'Deamon Slayer 2';
const updatedDocument = await hydratedDetails.save();

So you might as well not use lean() in the first place.

However, I don't think it is going to work for you anyway because foundSeat is the result of filter() and map() which return new arrays. It is a new variable and is not part of the getDetails object anymore. When you set new values on foundSeat those changes aren't reflected in getDetails.

Your problems stem from not being able to select the correct timeslots. You are using the arrays index such as getDetails.timeslots[0].seats to pick one from the array because you have not modelled your data well. Your timelsots should be selected by a resource identifier such _id. Then you would be able to perform a findOneAndUpdate query.