1

I've got a head-scratcher here that I'd like to share with you all.

So here's the model:

    _id: ObjectId()
    name: String,
    columns: [
      {
        name: String,
        _id: ObjectId()
        tasks: [
          {
            title: String,
            description: String,
            status: String,
            _id: ObjectId()
            subtasks: [
              {
                title: String,
                isCompleted: Boolean,
              },
            ],
          },
        ],
      },
    ],
  });

and the query:

exports.createSubtask = (req, res) => {
  if (!req.body) {
    res.status(400).send({ message: "Task name can not be empty!" });
    return;
  }

  const board = req.params.board;
  const column = req.params.column;
  const task = req.params.task;

  Board.findOneAndUpdate(
    {
      _id: board,
      "columns._id": column,
      "columns.tasks._id": task,
    },
    {
      $push: {
        "columns.$.tasks.$.subtasks": req.body,
      },
    }
  )
    .then((data) => {
      if (!data) {
        res.status(404).send({
          message: `Cannot update Task with id=${task}. Maybe task was not found!`,
        });
      } else res.send({ message: "Task was updated successfully." });
    })
    .catch((err) => {
      res.status(500).send({
        message: "Error updating Task with id=" + task,
      });
    });
};

I'm trying to push an object into the subtasks array with $push, but Postman is throwing an error.

Any ideas as to what I'm doing wrong? Appreciate the help.

  • Golden Ratio

However, I was able to successfully push an object into the tasks array with the following query:

exports.createTask = (req, res) => {
  if (!req.body) {
    res.status(400).send({ message: "Task name can not be empty!" });
    return;
  }

  const board = req.params.board;
  const column = req.params.column;

  Board.findOneAndUpdate(
    {
      _id: board,
      "columns._id": column,
    },
    {
      $push: {
        "columns.$.tasks": req.body,
      },
    }
  )
    .then((data) => {
      if (!data) {
        res.status(404).send({
          message: `Cannot update Column with id=${column}. Maybe column was not found!`,
        });
      } else res.send({ message: "Column was updated successfully." });
    })
    .catch((err) => {
      res.status(500).send({
        message: "Error updating Column with id=" + column,
      });
    });
};

2 Answers 2

2

It is not possible to use multiple positional $ for the nested array as mention in docs:

The positional $ operator cannot be used for queries which traverse more than one array, such as queries that traverse arrays nested within other arrays, because the replacement for the $ placeholder is a single value

You should work with the positional filtered operator $[<identifier>].

Board.findOneAndUpdate(
    {
      _id: board,
      "columns._id": column,
      "columns.tasks._id": task,
    },
    {
      $push: {
        "columns.$.tasks.$[task].subtasks": req.body,
      },
    },
    {
      arrayFilters: [
        { "task._id": task }
      ]
    }
  )
.then(...);

Note: Ensure that the passed in task is ObjectId type.

Sign up to request clarification or add additional context in comments.

Comments

0

Credit to Yong Shun Yong for the help. Through trial and error, I solved the problem with the following code

 Board.findOneAndUpdate(
{
  _id: board,
  "columns._id": column,
},
{
  $push: {
    "columns.$.tasks.$[].subtasks": req.body,
  },
},
{
  arrayFilters: [{ "task._id": task }],
}

)

2 Comments

Hi, if you $[] all positional operator, you can remove the arrayFilters part. As arrayFilters part we use to filter the document within nested array, but for your current query, that part is not needed.
You're absolutely right. I reverted to your solution and it worked. It turns out, I put an 's' after task in the $[] subarray.

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.