Error: Unable to delete subdocument from array in Mongoose

In my code, I have a UserModel that is defined as follows:

import mongoose from "mongoose";

const UserSchema = new mongoose.Schema(
  {
    username: {
      type: String,
      required: true,
    },
    email: {
      type: String,
      required: true,
    },
    password: {
      type: String,
      required: true,
    },
    notes: [],
  },
  { timestamps: true }
);

const UserModel = mongoose.model("user", UserSchema);

export { UserModel };

I also have a function that adds notes to the notes array of a user:

export default async (req, res) => {
  const {
    text,
    title,
    userId,
  } = req.body;

  const currentUser = await UserModel.findById(userId);
  
  const note = new NoteModel({
    title,
    text,
  });

  currentUser.notes.push(note);
  await currentUser.save();
  res.json(currentUser);
};

This function works correctly. Now, I am trying to implement a function to delete notes from a user's notes array:

export default async (req, res) => {
  const { id: noteId } = req.params;

  const user = await UserModel.findById(req.body.userId);
  user.notes.pull(noteId);

  await user.save();
  res.json(user);
};

However, the note is not getting deleted as expected. I have tried the following methods:

  • await user.notes.pull(noteId).

  • (with and without awaiting)user.notes.pull({_id: noteId)}.

UserModel.update( 
    { _id: userId},
    {
        $pull: {
            notes: { _id : noteId }
        }
    },
  • Trying to remove the note using JavaScript array methods like filter, splice, slice, and spread.

Unfortunately, none of these approaches seem to be working in deleting the note. What could be the issue here?

Answer №1

As per the guidelines in Subdocuments Removal documentation, the process is functioning correctly.

For example:

models/user.ts:

import mongoose from "mongoose";
import { NoteSchema } from "./note";

const UserSchema = new mongoose.Schema(
  {
    username: { type: String, required: true },
    email: { type: String, required: true },
    password: { type: String, required: true },
    notes: [NoteSchema],
  },
  { timestamps: true }
);

export const UserModel = mongoose.model("user", UserSchema);

models/note.ts:

import mongoose from "mongoose";

export const NoteSchema = new mongoose.Schema(
  {
    title: { type: String, required: true },
    text: { type: String, required: true },
  },
  { timestamps: true }
);

export const NoteModel = mongoose.model("note", NoteSchema);

main.ts:

import { UserModel } from './models/user';
import mongoose from 'mongoose';
import { config } from '../../src/config';

async function main() {
  mongoose.connect(config.MONGODB_URI, { useNewUrlParser: true, useUnifiedTopology: true });
  const db = mongoose.connection;
  db.on('error', console.error.bind(console, 'connection error:'));
  db.once('open', async () => {
    // seed
    const user = new UserModel({ username: 'teresa teng', email: '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c4b0a1b6a1b7a5eab0a1aaa384a1bca5a9b4a8a1eaa7aba9">[email protected]</a>', password: '123456', notes: [{ title: 'a', text: 'a-text' }, { title: 'b', text: 'b-text' }] });
    await user.save();

    // query a user and remote a note
    const userDoc1 = await UserModel.findOne({ username: 'teresa teng' });
    console.log('userDoc1: ', userDoc1);
    userDoc1.notes.pull('6453682c4fd3563f4b9ccb0b');
    await userDoc1.save();

    // query the user and check notes
    const userDoc2 = await UserModel.findOne({ username: 'teresa teng' });
    console.log('userDoc2: ', userDoc2);
    db.close();
  })
}

main();

Execution logs:

userDoc1:  {
  _id: 6453682c4fd3563f4b9ccb0a,
  username: 'teresa teng',
  email: '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="6a1e0f180f190b441e0f040d2a0f120b071a060f44090507">[email protected]</a>',
  password: '123456',
  notes: [
    {
      _id: 6453682c4fd3563f4b9ccb0b,
      title: 'a',
      text: 'a-text',
      createdAt: 2023-05-04T08:09:16.818Z,
      updatedAt: 2023-05-04T08:09:16.818Z
    },
    {
      _id: 6453682c4fd3563f4b9ccb0c,
      title: 'b',
      text: 'b-text',
      createdAt: 2023-05-04T08:09:16.818Z,
      updatedAt: 2023-05-04T08:09:16.818Z
    }
  ],
  createdAt: 2023-05-04T08:09:16.819Z,
  updatedAt: 2023-05-04T08:09:16.819Z,
  __v: 0
}
userDoc2:  {
  _id: 6453682c4fd3563f4b9ccb0a,
  username: 'teresa teng',
  email: '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="057160776076642b71606b6245607d64687569602b666a68">[email protected]</a>',
  password: '123456',
  notes: [
    {
      _id: 6453682c4fd3563f4b9ccb0c,
      title: 'b',
      text: 'b-text',
      createdAt: 2023-05-04T08:09:16.818Z,
      updatedAt: 2023-05-04T08:09:16.818Z
    }
  ],
  createdAt: 2023-05-04T08:09:16.819Z,
  updatedAt: 2023-05-04T08:13:58.452Z,
  __v: 1
}

package version:

"mongodb": "^3.6.3",
"mongoose": "^5.11.9",

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Determining the frequency of a specific pattern within an array

I am working with an array that looks like this: a= ["foo", "bar", "baz", "foo", "bar", "baz", "foo", "bar", "BAD," "baz"] It's clear that there is a repeating pattern in the array: "foo", "bar", "baz" except for the last pattern, which includes ...

Preventing users from using alt+tab on an IE8 aspx web page

I need help with disabling the alt+tab function in my IE8 web browser for a page that displays a modal dialogue. Can anyone assist me with this issue? ...

Exploring the possibility of designing custom pageload tooltips inspired by jQuery validationEngine's visual style and interface

My website incorporates the jQuery.validationEngine plugin to ensure the accuracy of user input. The tooltips that accompany this validation feature are particularly appealing; they gracefully fade in and vanish when users interact with them. To visualize ...

Cross-Origin Resource Sharing is enabled yet I am still encountering the error message: "The origin has been blocked by CORS policy because no 'Access-Control-Allow-Origin' header is present."

I am facing a CORS error whenever I try to redirect the browser from the backend. Despite using the CORS package in the backend, it seems like it is not functioning as expected. Below is the code snippet from the client-side: useEffect(() => { async ...

Enable erase functionality for touchscreen interactions (TouchEvent)

I have created a fun game where players must erase a colored layer to reveal an image. However, I am facing an issue as the game only works on my desktop and not on touchscreens like iPhones or iPads. I believe I need to replace MouseEvent with TouchEvent, ...

I'm currently leveraging Vue.js and Python Flask for my backend development. I'm looking to establish some local variables. What is the best way to accomplish this?

Here is my Vue js file where I am utilizing two URLs from localhost. My goal is to create a configuration file that will allow me to make changes in one place and have those changes reflected throughout. <template> <div> <div class="glob ...

Occasionally, an AJAX request may be terminated when making multiple calls to the API

Within an application environment, a URL is being called via AJAX four times. Interestingly, on a specific page, the AJAX request gets canceled when attempting the fourth invocation. The fourth request shows "Provisional headers are shown" in its request ...

Is there a way to retrieve the HTML raw code using backticks for string interpolation in JavaScript?

I am working on a resume builder project where the HTML template file is stored in Firebase storage and retrieved using a URL. The template has been modified to include string interpolation, such as <h1>${name}</h1>. However, when I fetch the d ...

Here's a new version: "Strategies for deactivating a text field in a desktop application that

I am currently using WiniumDriver to automate a desktop application. My goal is to disable a text field once a value has been entered into it. // Launch the desktop application WiniumDriver driver = null; DesktopOptions option = new DesktopOptions(); o ...

Issue: unhandled exception: Marketplace URI is not valid

It seems like I am the first one in this community to ask a question related to balancedpayments. I recently started working with balancedpayments. Here's what I've done so far: Set up a test marketplace Added a "webhoo ...

NodeJS Splitting String by Multiple Spaces Tutorial

When working in Node.js, I encountered the following: >out 'java 1303 root 187u CHR 166,0 0t0 14586 /dev/ttyACM0\n' >typeof out 'string' > out.split("\\s+"); [ 'java 1303 root 187u CHR 16 ...

Utilize RSelenium to showcase all rows in the display

I am encountering an issue while trying to extract data from the following website: . On this website, there is a table consisting of 1874 rows. Despite my efforts to scrape it, I was only able to retrieve the first 10 rows due to the default lengthMenu ...

The remote DDP connection to the Meteor collection is restricted from performing update operations

I am currently setting up a connection between two Meteor applications: App A and App B, where the database is located. In App A: remote = DDP.connect('http://url.of.app.B'); Booking = new Mongo.Collection('booking', remote); Booking.a ...

What is the best way to ensure messages are sequentially delivered in NodeJS?

I've successfully deployed a node server responsible for updating the database with the connectivity status of IOT devices. Issue Due to the asynchronous nature of NodeJS and its single-threaded execution, there is a possibility of receiving confli ...

Adding or removing rows within an array in a hybrid Vue project - a step-by-step guide

Recently, I created a small web application to assist in organizing my project ideas. Check it out here: https://codepen.io/aibrindley/pen/ELXajM Now, I am working on enabling users to add items to the array directly from the interface. It would also be c ...

Dividing the text by its position value and adding it to a fresh object

I needed to divide the paragraph into sections based on its entityRanges. Here is what the original paragraph looks like: { type: 'paragraph', depth: 1, text: 'Do you have questions or comments and do you wish to contact ABC? P ...

Is it a good idea to resize images sourced from other websites before displaying them on your

I am currently working on a project that involves fetching images from various websites and displaying a thumbnail or resized version of the original image. Since I will be fetching many images at once, loading the original image files can take longer. ...

What is the process for searching my database and retrieving all user records?

I've been working on testing an API that is supposed to return all user documents from my Mongo DB. However, I keep running into the issue of receiving an empty result every time I test it. I've been struggling to pinpoint where exactly in my cod ...

Updating NPM packages versions is currently restricted

I'm in the process of creating a Next.JS application using create-next-app. However, I've noticed that in the package.json file it lists the following dependencies: "eslint": "8.43.0", "eslint-config-next": &quo ...

How can I display different divs based on a selected option?

I'm encountering difficulties while attempting to develop the code for this specific task. My goal is to display or hide divs based on the selection made in a select option, with a total of 4 options available. There are 2 select elements <select ...