Search code examples
node.jsmongodbmongoosesubdocument

Mongoose - Get and Delete a subrecord


I have a model defined as so:

const mongoose = require('mongoose');

const Schema = mongoose.Schema;

const feedbackSchema = new Schema({
  Name: {
    type: String,
    required: true,
  },
  Email: {
    type: String,
    required: true,
  },
  Project: {
    type: String,
    required: true,
  },
  Wonder: {
    type: String,
    required: true,
  },
  Share: {
    type: String,
    required: true,
  },
  Delight: {
    type: String,
    required: true,
  },
  Suggestions: {
    type: String,
    required: true,
  },
  Rating: {
    type: String,
    required: true,
  },
  dateCreated: {
    type: Date,
    default: Date.now(),
  },
  user: {
    type: Schema.Types.ObjectId,
    ref: 'User'
  }

});

const UserSchema = new Schema({
  googleId: {
    type: String
  },
  displayName: {
    type: String
  },
  firstName: {
    type: String
  },
  lastName: {
    type: String
  },
  image: {
    type: String
  },
  createdAt: {
    type: Date,
    default: Date.now(),
  },

  feedback: [feedbackSchema],
})

module.exports = mongoose.model("User", UserSchema);

An example document:

{
    _id: ObjectId('60b9dc728a516a4669b40dbc'),
    createdAt: ISODate('2021-06-04T07:42:01.992Z'),
    googleId: '2342987239823908423492837',
    displayName: 'User Name',
    firstName: 'User',
    lastName: 'Name',
    image: 'https://lh3.googleusercontent.com/a-/89wf323wefiuhh3f9hwerfiu23f29h34f',
    feedback: [
        {
            dateCreated: ISODate('2021-06-04T07:42:01.988Z'),
            _id: ObjectId('60b9dc858a516a4669b40dbd'),
            Name: 'Joe Bloggs',
            Email: '[email protected]',
            Project: 'Some Project',
            Suggestions: 'Here are some suggestions',
            Rating: '10'
        },
        {
            dateCreated: ISODate('2021-06-04T08:06:44.625Z'),
            _id: ObjectId('60b9df29641ab05db7aa2264'),
            Name: 'Mr Bungle',
            Email: 'mr@bungle',
            Project: 'The Bungle Project',
            Suggestions: 'Wharghable',
            Rating: '8'
        },
        {
            dateCreated: ISODate('2021-06-04T08:08:30.958Z'),
            _id: ObjectId('60b9df917e85eb6066049eed'),
            Name: 'Mike Patton',
            Email: '[email protected]',
            Project: 'No More Faith',
            Suggestions: 'Find the faith',
            Rating: '10'
        },
    ],
    __v: 0
}

I have two routes defined, the first one is called when the user clicked a button on a feedback item on the UI which takes the user to a "are you sure you want to delete this record"-type page displaying some of the information from the selected feedback record.

A second route which, when the user clicks 'confirm' the subrecord is deleted from the document.

The problem I'm having is I can't seem to pull the feedback from the user in order to select the document by id, here's what I have so far for the confirmation route:

router.get('/delete', ensureAuth, async (req, res) => {
    try {
        var url = require('url');
        var url_parts = url.parse(req.url, true);
        var feedbackId = url_parts.query.id;

        const allFeedback = await User.feedback;
        const feedbackToDelete = await allFeedback.find({ _id: feedbackId });

        console.log(feedbackToDelete);

        res.render('delete', {
            imgSrc: user.image,
            displayName: user.firstName,
            feedbackToDelete
        });
    } catch (error) {
        console.log(error);
    }
})

Help much appreciated


Solution

  • Update

    You should be able to do just this:

    const feedbackToDelete = await User.feedback.find({ _id: feedbackId });

    Or if feedbackId is just a string, which is appears to be, you may have to do something like:

    // Create an actual _id object
    // That is why in your sample doc you see ObjectId('foobarbaz')
    const feedbackId = new mongoose.Types.ObjectId(url_parts.query.id);
    const feedbackToDelete = await User.feedback.find({ _id: feedbackId });
    

    Original

    Shouldn't this:

    const allFeedback = await User.feedback; (a field)

    be this:

    const allFeedback = await User.feedback(); (a method/function)

    ?