How to return single object (mongoose/mongoDB)

Issue

I have this data stored in database.

{
  "_id": "62fa5aa25778ec97bc6ee231",
  "user": "62f0eb5ebebd0f236abcaf9d",
  "name": "Marketing Plan",
  "columns": [
    {
      "name": "todo",
      "_id": "62fa5aa25778ec97bc6ee233",
      "tasks": [
        {
          "title": "Task Four testing 2",
          "description": "This is task four",
          "subtasks": [
            {
              "name": "wash dshes test",
              "completed": false,
              "_id": "62ff74bfe80b11ade2d34456"
            },
            {
              "name": "do homework",
              "completed": false,
              "_id": "62ff74bfe80b11ade2d34457"
            }
          ],
          "_id": "62ff74bfe80b11ade2d34455"
        }
      ]
    },
    {
      "name": "doing",
      "_id": "62fa5aa25778ec97bc6ee234",
      "tasks": []
    },
    {
      "name": "done",
      "_id": "62fa5aa25778ec97bc6ee235",
      "tasks": []
    }
  ],
  "__v":0
}

I want to be able to return a single object with the id equal to the req.params.id, in this case that would be 62ff74bfe80b11ade2d34455.

{
  "title": "Task Four testing 2",
  "description": "This is task four",
  "subtasks": [
    {
      "name": "wash dshes test",
      "completed": false,
      "_id": "62ff74bfe80b11ade2d34456"
    },
    {
      "name": "do homework",
      "completed": false,
      "_id": "62ff74bfe80b11ade2d34457"
    }
  ],
  "_id": "62ff74bfe80b11ade2d34455"
}

I researched stackoverflow and came across this potential solution: Mongoose retrieve one document from nested array which implemented the aggregate framework. But when I test this in postman, the request isn’t made.

const getTask = asyncHandler(async (req, res) => {
  const task = await Board.aggregate([
    {
      $match: {
        "columns.tasks._id": req.params.id,
      },
    },
    {
      $project: {
        columns: {
          $first: {
            $filter: {
              input: "$columns.tasks",
              cond: {
                $eq: ["$$this._id", req.params.id],
              },
            },
          },
        },
      },
    },
    {
      $replaceRoot: {
        newRoot: "$columns",
      },
    },
  ]);
});

Solution

Having an array inside an array complicates the query a bit, but here’s one way to retrieve the data you want.

db.Board.aggregate([
  {
    $match: {
      "columns.tasks._id": req.params.id
    }
  },
  {"$unwind": "$columns"},
  {
    $match: {
      "columns.tasks._id": req.params.id
    }
  },
  {
    "$project": {
      "task": {
        "$first": {
          "$filter": {
            "input": "$columns.tasks",
            "cond": {"$eq": ["$$this._id", req.params.id]}
          }
        }
      }
    }
  },
  {"$replaceWith": "$task"}
])

Try it on mongoplayground.net. [The mongoplayground.net example uses "62ff74bfe80b11ade2d34455" rather than req.params.id.]

Answered By – rickhg12hs

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published