1

I'm trying to remove an object from an array in a document using mongoose.

This is an example of an entry:

{
  _id: "12345",
  folder: {
    name: "Folder1",
    files: [
      {
        fileName: "File 1",
        fileID: "6789",
        folderID: "12345"
      }
    ],
    active: true
  }
}

This is what I am currently doing to remove the file from the array. The Attachment.unlink is what removes the file from the gridfs filestore. That part of the code works. My object however will not remove from the array.

router.delete("/filesystem/:id", (req, res, next) => {
  Attachment.unlink(req.params.id, (error, attachment) => {
    if (!attachment) return res.status(404);
    if (error) return next(error);
    Folder.findByIdAndUpdate(
      {
        _id: req.body.folderID
      },
      {
        $pull: {
          "folder.files": {
            $elemMatch: { fileID: req.params.id }
          }
        }
      },
      { multi: true, safe: true },
      (error, folder) => {
        if (error) return next(error);
        return res.status(200).json({
          folder
        });
      }
    );
  });
});

I have also tried to use update rather than findByIdAndUpdate. How do I remove an object from the array where the fileID is 6789?

4
  • Have also tried casting type objectID mongoose.Types.ObjectId(req.params.id) Commented Jun 7, 2019 at 14:13
  • Do your subdocuments have _ids? If so you could do folder.files.id(fileId).remove(). See mongoosejs.com/docs/subdocs.html#removing-subdocs Commented Jun 7, 2019 at 14:19
  • They do not have _ids it is all one schema Commented Jun 7, 2019 at 14:27
  • Have you tried $pull: { "folder.files": { fileID: req.params.id } } instead of $elemMatch? Commented Jun 7, 2019 at 14:35

1 Answer 1

0

You should be able to use array.pull (see https://mongoosejs.com/docs/api.html#mongoosearray_MongooseArray-pull)

Below is a sample where I've modified your code and used async/await instead of callbacks.

router.delete("/filesystem/:id", (req, res, next) => {
  Attachment.unlink(req.params.id, async (error, attachment) => {
    if (!attachment) return res.status(404);
    if (error) return next(error);

    try {
      const folder = await Folder.findById(req.body.folderID);
      folder.folder.files.pull({ fileID: req.params.id });
      await folder.save();

      return res.status(200).json({
        folder
      });
    } catch (error) {
      return next(error);
    }
  });
});
Sign up to request clarification or add additional context in comments.

5 Comments

This gets the value of the whole array
Are you certain? Pull should remove it from the object. Obviously you have to complete the save as per my example, otherwise the change won't be saved to the database.
I just realized that your Folder model has a "folder" field, so it's folder.folder.files.pull and not folder.files.pull.
Yes I recognized that and tried it the correct way. I believe the pull may not be working because it is not another Schema or an ObjectID like the docs state
I dunno, I have a feeling that something else is wrong since neither array.pull or findByIdAndUpdate is working for you. Can you find the object in the array if you use for example const file = folder.folder.files.find(file => file.fileID === req.params.id) in my code sample? Are you sure the field name is fileID? Are you sure the value isn't wrong (i.e. req.params.id is a Number but fileID expects a String

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.