1

So I have the following document, its kind of a board the includes lists that includes tasks (like todo list)

{
    "boardMembers": [
        "5f636a5c0d6fa84be48cc19d",
    ],
    "boardLists": [
        {
            "cards": [
                {
                    "_id": "5f7c9b77eb751310a41319ab",
                    "text": "task one"
                },
                {
                    "_id": "5f7c9bb524dd8d42d469bba3",
                    "text": "task two"
                }
            ],
            "_id": "5f7c9b6b02c19f21a493cb7d",
            "title": "List one",
            "__v": 0
        }
    ],
    "_id": "5f63877177beba2e3c15d159",
    "boardName": "board1",
    "boardPassword": "123456",
    "boardCreator": "5f636a5c0d6fa84be48cc19d",
    "g_createdAt": "2020-09-17T15:57:37.616Z",
    "__v": 46
}

How can I update and delete one of those cards? (I dont have a task schema, I want to delete the task from the board document

I tried this:

router.put("/delete-task/:list/:task", auth, boardAuth, async (req, res) => {
  const listId = req.params.list;
  const task = req.params.task;

  const board = await Board.findOne({ _id: req.board._id });
  if (!board) return res.status(404).send("no such board");

  Board.findOneAndUpdate(
    { _id: req.board._id },
    { $pull: { "boardLists.$[outer].cards": { _id: task } } },
    {
      arrayFilters: [{ "outer._id": listId }],
    }
  );
  res.send(board);
});

1 Answer 1

1

Use filtered positional operator $[<identifier>] which identifies the array elements that match the arrayFilters for updates.

For updating an object in cards array:

Board.findOneAndUpdate(
  { _id: "boardId" },
  { $set: { "boardLists.$[outer].cards.$[inner].text": "update value" } },
  {
    arrayFilters: [
      { "outer._id": "boardListId" },
      { "inner.text": "task two" },
    ]
  }
);

For removing an object in cards array use $pull

Board.findOneAndUpdate(
  { _id: "boardId" },
  { $pull: { "boardLists.$[outer].cards": { text: "task two" } } },
  {
    arrayFilters: [{ "outer._id": "boardListId" }],
  }
);
Sign up to request clarification or add additional context in comments.

4 Comments

What the outer and inner means? And if i want to filter by id and not text
@Timo222 They are just positional identifier for the objects in the array boardList and cards i;e which object to refer to in these array (and also used to put filter on which object using arrayFilters) They could be given other name as well like: boardLists.$[i].cards.$[j].text . For simplicity I named them outer and inner.
@Timo222 And you can filter by id too or any other property.
@Timo222 If task at { _id: task } and listId are incoming as strings, you may want to cast them as instance of ObjectId. Example: { _id: new mongoose.Types.ObjectId(task)} and new mongoose.Types.ObjectId(listId) and try that out.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.