Array related aggregation functions ($arrayElemAt, $concatArrays, $filter, $isArray, $size, $slice, $map, $reduce, $zip, $in, $arrayToObject, $objectToArray, $first, $last, $reverseArray, $range, $indexOfArray, $push, $addToSet, $setUnion, $setIntersection, $setDifference, $setEquals, $sortArray)

  • To explain each MongoDB array related aggregation function, let's first create a sample dataset collection that you can reference throughout your explanations.
  • Sample Dataset (Collection: students)


    db.students.insertMany([
        {
            "_id": 1,
            "name": "John",
            "subjects": ["Math", "Science", "History"],
            "scores": [85, 90, 75],
            "age": 17
        },
        {
            "_id": 2,
            "name": "Jane",
            "subjects": ["English", "Math", "Geography"],
            "scores": [95, 80, 85],
            "age": 18
        },
        {
            "_id": 3,
            "name": "David",
            "subjects": ["Science", "Math", "History"],
            "scores": [88, 92, 79],
            "age": 16
        }
    ])

  • This collection represents students, their respective subjects, and the scores they received. Now, let’s explain each array aggregation function using this dataset.

$arrayElemAt

  • The $arrayElemAt operator returns the element at a specified index in an array. The index starts at 0 for the first element.
  • Example: If you want to retrieve the second subject for each student:


    db.students.aggregate([
        {
            $project: {
                name: 1,
                secondSubject: { $arrayElemAt: ["$subjects", 1] }
            }
        }
    ])

    // Output
    [
        { "_id": 1, "name": "John", "secondSubject": "Science" },
        { "_id": 2, "name": "Jane", "secondSubject": "Math" },
        { "_id": 3, "name": "David", "secondSubject": "Math" }
    ]

$concatArrays

  • The $concatArrays operator concatenates multiple arrays into a single array.
  • Example: Suppose you want to merge the subjects and scores arrays into one array for each student:


    db.students.aggregate([
        {
            $project: {
                name: 1,
                mergedArray: { $concatArrays: ["$subjects", "$scores"] }
            }
        }
    ])

    // Output
    [
      {
        "_id": 1, "name": "John", "mergedArray": [
          "Math", "Science", "History", 85, 90, 75
        ]
      },
      {
        "_id": 2, "name": "Jane", "mergedArray": [
          "English", "Math", "Geography", 95, 80, 85
        ]
      },
      {
        "_id": 3, "name": "David", "mergedArray": [
          "Science", "Math", "History", 88, 92, 79
        ]
      }
    ]

$filter

  • The $filter operator returns a subset of an array based on a condition.
  • Example: If you want to get all scores greater than 80 for each student:


    db.students.aggregate([
        {
            $project: {
                name: 1,
                highScores: {
                    $filter: {
                        input: "$scores",
                        as: "score",
                        cond: { $gt: ["$$score", 80] }
                    }
                }
            }
        }
    ])

    // Output
    [
        { "_id": 1, "name": "John", "highScores": [85, 90] },
        { "_id": 2, "name": "Jane", "highScores": [95, 85] },
        { "_id": 3, "name": "David", "highScores": [88, 92] }
    ]

$isArray

  • The $isArray operator checks if a field is an array.
  • Example: Check if the subjects field is an array for each student:


    db.students.aggregate([
      {
        $project: {
          name: 1,
          isSubjectsArray: { $isArray: "$subjects" }
        }
      }
    ])
    
    // Output
    [
      { "_id": 1, "name": "John", "isSubjectsArray": true },
      { "_id": 2, "name": "Jane", "isSubjectsArray": true },
      { "_id": 3, "name": "David", "isSubjectsArray": true }
    ]

$size

  • The $size operator returns the number of elements in an array.
  • Example: Find out how many subjects each student is taking:


    db.students.aggregate([
      {
        $project: {
          name: 1,
          subjectCount: { $size: "$subjects" }
        }
      }
    ])

    // Output
    [
      { "_id": 1, "name": "John", "subjectCount": 3 },
      { "_id": 2, "name": "Jane", "subjectCount": 3 },
      { "_id": 3, "name": "David", "subjectCount": 3 }
    ]

$slice

  • The $slice operator returns a subset of an array based on the provided parameters.

  • Example: Get the first two subjects for each student:


    db.students.aggregate([
      {
        $project: {
          name: 1,
          firstTwoSubjects: { $slice: ["$subjects", 2] }
        }
      }
    ])

    // Output
    [
      { "_id": 1, "name": "John", "firstTwoSubjects": ["Math", "Science"] },
      { "_id": 2, "name": "Jane", "firstTwoSubjects": ["English", "Math"] },
      { "_id": 3, "name": "David", "firstTwoSubjects": ["Science", "Math"] }
    ]

$map

  • The $map operator applies an expression to each element in an array and returns the transformed array.
  • Example: Suppose you want to add 5 points to each student's scores:


    db.students.aggregate([
      {
        $project: {
          name: 1,
          adjustedScores: {
            $map: {
              input: "$scores",
              as: "score",
              in: { $add: ["$$score", 5] }
            }
          }
        }
      }
    ])

    // Output
    [
      { "_id": 1, "name": "John", "adjustedScores": [90, 95, 80] },
      { "_id": 2, "name": "Jane", "adjustedScores": [100, 85, 90] },
      { "_id": 3, "name": "David", "adjustedScores": [93, 97, 84] }
    ]

$reduce

  • The $reduce operator reduces an array to a single value based on an accumulator.
  • Example: Calculate the total score for each student:


  db.students.aggregate([
    {
      $project: {
        name: 1,
        totalScore: {
          $reduce: {
            input: "$scores",
            initialValue: 0,
            in: { $add: ["$$value", "$$this"] }
          }
        }
      }
    }
  ])

  // Output
  [
    { "_id": 1, "name": "John", "totalScore": 250 },
    { "_id": 2, "name": "Jane", "totalScore": 260 },
    { "_id": 3, "name": "David", "totalScore": 259 }
  ]

$zip

  • The $zip operator merges arrays element-wise into an array of arrays.
  • Example: Combine subjects and scores into pairs for each student:


    db.students.aggregate([
      {
        $project: {
          name: 1,
          subjectScorePairs: {
            $zip: {
              inputs: ["$subjects",
                "$scores"]
            }
          }
        }
      }
    ])

    // Output
    [
      {
        "_id": 1,
        "name": "John",
        "subjectScorePairs": [
          ["Math", 85], ["Science", 90], ["History", 75]
        ]
      },
      {
        "_id": 2,
        "name": "Jane",
        "subjectScorePairs": [
          ["English", 95], ["Math", 80], ["Geography", 85]
        ]
      },
      {
        "_id": 3,
        "name": "David",
        "subjectScorePairs": [
          ["Science", 88], ["Math", 92], ["History", 79]
        ]
      }
    ]

$in

  • The $in operator checks if a specified value exists in an array.
  • Example: Find students who are taking the subject "Math":

    db.students.aggregate([
      {
        $match: {
          subjects: { $in: ["Math"] }
        }
      }
    ])

    // Output
    [
      { "_id": 1, "name": "John", "subjects": ["Math", "Science", "History"] },
      { "_id": 2, "name": "Jane", "subjects": ["English", "Math", "Geography"] },
      { "_id": 3, "name": "David", "subjects": ["Science", "Math", "History"] }
    ]


$arrayToObject
  • The $arrayToObject operator converts an array of key-value pairs into a document (object).
  • Example: Suppose you have an array of pairs (e.g., subject-score) and you want to convert it into a document where subjects are the keys and their respective scores are the values:

  db.students.aggregate([
    {
      $project: {
        name: 1,
        subjectScoreDoc: {
          $arrayToObject: {
            $zip: { inputs: ["$subjects", "$scores"] }
          }
        }
      }
    }
  ])

  // Output
  [
    {
      "_id": 1,
      "name": "John",
      "subjectScoreDoc": {
        "Math": 85,
        "Science": 90,
        "History": 75
      }
    },
    {
      "_id": 2,
      "name": "Jane",
      "subjectScoreDoc": {
        "English": 95,
        "Math": 80,
        "Geography": 85
      }
    },
    {
      "_id": 3,
      "name": "David",
      "subjectScoreDoc": {
        "Science": 88,
        "Math": 92,
        "History": 79
      }
    }
  ]


$objectToArray
  • The $objectToArray operator converts a document (object) into an array of key-value pairs.
  • Example: Let’s reverse the previous operation by converting the subjectScoreDoc back to an array of key-value pairs:

    db.students.aggregate([
      {
        $project: {
          name: 1,
          subjectScoreArray: {
            $objectToArray: {
              "Math": 85,
              "Science": 90,
              "History": 75
            }
          }
        }
      }
    ])

    //  Output
    [
      {
        _id: 1,
        name: 'John',
        subjectScoreArray: [
          { k: 'Math', v: 85 },
          { k: 'Science', v: 90 },
          { k: 'History', v: 75 }
        ]
      },
      {
        _id: 2,
        name: 'Jane',
        subjectScoreArray: [
          { k: 'Math', v: 85 },
          { k: 'Science', v: 90 },
          { k: 'History', v: 75 }
        ]
      },
      {
        _id: 3,
        name: 'David',
        subjectScoreArray: [
          { k: 'Math', v: 85 },
          { k: 'Science', v: 90 },
          { k: 'History', v: 75 }
        ]
      }
    ]


$first
  • The $first operator returns the first element in an array.
  • Example: If you want to get the first subject of each student:

    db.students.aggregate([
      {
        $project: {
          name: 1,
          firstSubject: { $first: "$subjects" }
        }
      }
    ])

    //  Output
    [
      { _id: 1, name: 'John', firstSubject: 'Math' },
      { _id: 2, name: 'Jane', firstSubject: 'English' },
      { _id: 3, name: 'David', firstSubject: 'Science' }
    ]


$last
  • The $last operator returns the last element in an array.
  • Example: If you want to get the last subject of each student:

    db.students.aggregate([
      {
        $project: {
          name: 1,
          lastSubject: { $last: "$subjects" }
        }
      }
    ])

    //  Output
    [
      { _id: 1, name: 'John', lastSubject: 'History' },
      { _id: 2, name: 'Jane', lastSubject: 'Geography' },
      { _id: 3, name: 'David', lastSubject: 'History' }
    ]


$reverseArray
  • The $reverseArray operator returns the elements of an array in reverse order.
  • Example: If you want to reverse the order of subjects for each student:

    db.students.aggregate([
      {
        $project: {
          name: 1,
          reversedSubjects: { $reverseArray: "$subjects" }
        }
      }
    ])

    //  Output
    [
      {
        _id: 1,
        name: 'John',
        reversedSubjects: ['History', 'Science', 'Math']
      },
      {
        _id: 2,
        name: 'Jane',
        reversedSubjects: ['Geography', 'Math', 'English']
      },
      {
        _id: 3,
        name: 'David',
        reversedSubjects: ['History', 'Math', 'Science']
      }
    ]


$range
  • The $range operator creates an array of numbers based on specified start, end, and step values.
  • Example: To generate an array of numbers from 1 to 5 for each student:

    db.students.aggregate([
      {
        $project: {
          name: 1,
          numberRange: { $range: [1, 6] }
        }
      }
    ])

    //  Output
    [
      { _id: 1, name: 'John', numberRange: [1, 2, 3, 4, 5] },
      { _id: 2, name: 'Jane', numberRange: [1, 2, 3, 4, 5] },
      { _id: 3, name: 'David', numberRange: [1, 2, 3, 4, 5] }
    ]


$indexOfArray
  • The $indexOfArray operator returns the index of the first occurrence of a specified value in an array.
  • Example: If you want to find the index of "Math" in each student's subjects:

    db.students.aggregate([
      {
        $project: {
          name: 1,
          indexOfMath: { $indexOfArray: ["$subjects", "Math"] }
        }
      }
    ])

    //  Output
    [
      { _id: 1, name: 'John', indexOfMath: 0 },
      { _id: 2, name: 'Jane', indexOfMath: 1 },
      { _id: 3, name: 'David', indexOfMath: 1 }
    ]


$push
  • The $push operator adds an element to an array. It's often used in the $group stage.
  • Example: Group students by their age and collect their names in an array:

    db.students.aggregate([
      {
        $group: {
          _id: "$age",
          studentNames: { $push: "$name" }
        }
      }
    ])

    //  Output
    [
      { _id: 17, studentNames: ['John'] },
      { _id: 18, studentNames: ['Jane'] },
      { _id: 16, studentNames: ['David'] }
    ]


$addToSet
  • The $addToSet operator adds an element to an array but only if it doesn't already exist in the array (eliminates duplicates).
  • Example: Group students by their age and collect unique subjects they are taking:

    db.students.aggregate([
      {
        $group: {
          _id: "$age",
          uniqueSubjects: { $addToSet: { $first: "$subjects" } }
        }
      }
    ])

    //  Output
    [
      { _id: 17, uniqueSubjects: ['Math'] },
      { _id: 18, uniqueSubjects: ['English'] },
      { _id: 16, uniqueSubjects: ['Science'] }
    ]


$setUnion
  • The $setUnion operator returns an array of all unique elements from multiple arrays.
  • Example: Find all unique subjects taken by all students:

    db.students.aggregate([{
      $project: {
        unionElements: { $setUnion: [["a", "b"], ["b", "c"]] }
      }
    }])

    // Output
    [
      { _id: 1, unionElements: ['a', 'b', 'c'] },
      { _id: 2, unionElements: ['a', 'b', 'c'] },
      { _id: 3, unionElements: ['a', 'b', 'c'] }
    ]


$setIntersection
  • The $setIntersection operator returns an array of elements that appear in all of the input arrays.
  • Example: Find the common subjects that all students are taking:

    db.students.aggregate([{
      $project: {
        commonElements: { $setIntersection: [["a", "b"], ["b", "c"]] }
      }
    }])

    // Output
    [
      { _id: 1, commonElements: ['b'] },
      { _id: 2, commonElements: ['b'] },
      { _id: 3, commonElements: ['b'] }
    ]


$setDifference
  • The $setDifference operator returns an array of elements that appear in the first array but not in the second.
  • Example: Find subjects that John is taking but David is not:

    db.students.aggregate([{
      $project: {
        diffElements: { $setDifference: [["a", "b"], ["b", "c"]] }
      }
    }])

    // Output
    [
      { _id: 1, diffElements: ['a'] },
      { _id: 2, diffElements: ['a'] },
      { _id: 3, diffElements: ['a'] }
    ]


$setEquals
  • The $setEquals operator returns true if two arrays contain the same elements, regardless of order.
  • Example: Check if two students are taking the same subjects:

    // Example 1
    db.students.aggregate([{
      $project: {
        eqElement: { $setEquals: [["a", "b"], ["b", "a"]] }
      }
    }])

    // Output
    [
      { _id: 1, eqElement: true },
      { _id: 2, eqElement: true },
      { _id: 3, eqElement: true }
    ]

    // Example 2
    db.students.aggregate([{
      $project: {
        eqElement: { $setEquals: [["a", "b"], ["a", "b"]] }
      }
    }])

    // Output
    [
      { _id: 1, eqElement: true },
      { _id: 2, eqElement: true },
      { _id: 3, eqElement: true }
    ]

    // Example 3
    db.students.aggregate([{
      $project: {
        eqElement: { $setEquals: [["a", "b"], ["a", "c"]] }
      }
    }])

    // Output
    [
      { _id: 1, eqElement: false },
      { _id: 2, eqElement: false },
      { _id: 3, eqElement: false }
    ]


$sortArray
  • The $sortArray operator sorts the elements of an array in ascending or descending order.
  • Example: Sort the scores array in descending order for each student:

    db.students.aggregate([
      {
        $project: {
          name: 1,
          sortedScores: { $sortArray: { input: "$scores", sortBy: -1 } }
        }
      }
    ])

    //  Output
    [
      { _id: 1, name: 'John', sortedScores: [90, 85, 75] },
      { _id: 2, name: 'Jane', sortedScores: [95, 85, 80] },
      { _id: 3, name: 'David', sortedScores: [92, 88, 79] }
    ]






No comments:

Post a Comment

Date and Time related aggregation functions ($year, $month, $dayOfMonth, $hour, $minute, $second, $dayOfWeek, $dateToString, $dateSubtract, $dateAdd, $isoWeek, $isoDayOfWeek, $dateTrunc, $dateFromString, $dateToParts, $dateFromParts, $dateDiff, $week)

In this blog post, we will explore Date/Time-related Aggregation Functions in MongoDB. MongoDB provides a robust set of aggregation operator...