Home > Back-end >  How do I fetch only the first element from the array?
How do I fetch only the first element from the array?

Time:05-01

How do I fetch only the first element from the "topicsName" array?

Data I have input:

    {
        "_id" : ObjectId("606b7046a0ccf72222c00c2f"),
        "groupId" : ObjectId("5f06cca74e51ba15f5167b86"),
        "insertedAt" : "2021-04-05T20:17:10.144521Z",
        "isActive" : true,
        "staffId" : [
            "606b6c34a0ccf72222c5a4df",
            "606b6c48a0ccf722228aa035"
        ],
        "subjectName" : "Maths",
        "teamId" : ObjectId("6069a6a9a0ccf704e7f4b537"),
        "updatedAt" : "2022-04-29T07:57:31.072067Z",
        "syllabus" : [
            {
                "chapterId" : "626b9b94ae6cd2092024f3ee",
                "chapterName" : "chap1",
                "topicsName" : [
                    {
                        "topicId" : "626b9b94ae6cd2092024f3ef",
                        "topicName" : "1.1"
                    },
                    {
                        "topicId" : "626b9b94ae6cd2092024f3f0",
                        "topicName" : "1.2"
                    }
                ]
            },
            {
                "chapterId" : "626b9b94ae6cd2092024f3f1",
                "chapterName" : "chap2",
                "topicsName" : [
                    {
                        "topicId" : "626b9b94ae6cd2092024f3f2",
                        "topicName" : "2.1"
                    },
                    {
                        "topicId" : "626b9b94ae6cd2092024f3f3",
                        "topicName" : "2.2"
                    }
                ]
            }
        ]
    }

The Query I used to try to fetch the element:- "topicId" : "626b9b94ae6cd2092024f3ef" from the "topicsName" array.

db.subject_staff_database
  .find(
    { _id: ObjectId("606b7046a0ccf72222c00c2f") },
    {
      syllabus: {
        $elemMatch: {
          chapterId: "626b9b94ae6cd2092024f3f1",
          topicsName: { $elemMatch: { topicId: "626b9b94ae6cd2092024f3f2" } },
        },
      },
    }
  )
  .pretty();


I was trying to fetch only the first element from the "topicsName" array, but it fetched both the elements in that array.

CodePudding user response:

You can do the followings in an aggregation pipeline.

  1. $match with your given id locate documents
  2. $reduce to flatten the syllabus and topicsName arrays
  3. $filter to get the expected element
db.collection.aggregate([
  {
    $match: {
      "syllabus.topicsName.topicId": "626b9b94ae6cd2092024f3ef"
    }
  },
  {
    "$project": {
      result: {
        "$reduce": {
          "input": "$syllabus.topicsName",
          "initialValue": [],
          "in": {
            "$concatArrays": [
              "$$value",
              "$$this"
            ]
          }
        }
      }
    }
  },
  {
    "$project": {
      result: {
        "$filter": {
          "input": "$result",
          "as": "r",
          "cond": {
            $eq: [
              "$$r.topicId",
              "626b9b94ae6cd2092024f3ef"
            ]
          }
        }
      }
    }
  }
])

Here is the Mongo playground for your reference.

CodePudding user response:

Welcome Ganesh Sowdepalli, You are not only asking to "fetch only the first element from the array", but to fetch only the matching element of a nested array property of an object item in array.

Edit: (according to @ray's comment) One way to do it is using an aggregation pipeline:

db.subject_staff_database.aggregate([
  {
    $match: {"_id": ObjectId("606b7046a0ccf72222c00c2f")}
  },
  {
    $project: {
      syllabus: {
        $filter: {
          input: "$syllabus",
          as: "item",
          cond: {$eq: ["$$item.chapterId", "626b9b94ae6cd2092024f3f1"
            ]
          }
        }
      }
    }
  },
  {
    $unwind: "$syllabus"
  },
  {
    $project: {
      "syllabus.topicsName": {
        $filter: {
          input: "$syllabus.topicsName",
          as: "item",
          cond: {$eq: ["$$item.topicId", "626b9b94ae6cd2092024f3f2"]}
        }
      },
      "syllabus.chapterId": 1,
      "syllabus.chapterName": 1,
      _id: 0
    }
  }
])

As you can see on this playground example.

If you want the actual first element, not by _id, look here on my first understanding to your question.

The aggregation pipeline allows us to do several operation on the results. Since syllabus is an array that may contain more than one matching chapterId, we need to $filter it for the items we want.

  • Related