Search code examples
mongodbmongodb-queryaggregation-frameworkaggregationfacet

How to find distinct values of fields using facet operation in mongodb


The filteredAccording part and the categorizedBy is working as expected using the query which I provided in the link but I am facing issues in the findDistinct part.

In mongodb I have the following data:

 {
        "_id": 10001,
        "university": "SPYU",
        "Courses": [
          "English",
          "French"
        ],
        "dept": [
          "Literature"
        ],
        "type": [
          "Autonomous"
        ],
        "status": "ACTIVE",
        "isMarked": true
      },
      {
        "_id": 10002,
        "university": "SPYU",
        "Courses": [
          "English",
          "French"
        ],
        "dept": [
          "Literature"
        ],
        "type": [
          "Autonomous"
        ],
        "status": "NON-ACTIVE",
        "isMarked": true
      }

I wanted the response to be:

 "university": [
  {
    "name": "Literature",
    "values": [
      {
        "_id": 10001,
        "university": "SPYU",
        "Courses": [
          "English",
          "French"
        ],
        "dept": [
          "Literature"
        ],
        "type": [
          "Autonomous"
        ],
        "status": "ACTIVE",
        "isMarked": true
      },
      {
        "_id": 10002,
        "university": "SPYU",
        "Courses": [
          "English",
          "French"
        ],
        "dept": [
          "Literature"
        ],
        "type": [
          "Autonomous"
        ],
        "status": "NON-ACTIVE",
        "isMarked": true
      }
    ]
  }
],
 "findDistinct": [
    {​​​​​​​​
      "name": "Courses",
      "values": [
        "English",
         "French"
      ]
    }​​​​​​​​,
    {​​​​​​​​
      "name": "Status",
      "values": [
        "ACTIVE",
        "NON-ACTIVE"
      ]
    }​​​​​​​​
  ]

I tried it using this link but the response is not coming as expected. https://mongoplayground.net/p/XECZvRMmt3T

Right now, the response is coming like this

 "universities": [
  {
    "name": "Literature",
    "values": [
      {
        "_id": 10001,
        "university": "SPYU",
        "Courses": [
          "English",
          "French"
        ],
        "dept": [
          "Literature"
        ],
        "type": [
          "Autonomous"
        ],
        "status": "ACTIVE",
        "isMarked": true
      },
      {
        "_id": 10002,
        "university": "SPYU",
        "Courses": [
          "English",
          "French"
        ],
        "dept": [
          "Literature"
        ],
        "type": [
          "Autonomous"
        ],
        "status": "NON-ACTIVE",
        "isMarked": true
      }
    ]
  }
],
"findDistinct": [
    {​​​​​​​​
      "Courses": [
        "English",
         "French"
      ]
    }​​​​​​​​,
    {​​​​​​​​
      "status": [
        "ACTIVE",
        "NON-ACTIVE"
      ]
    }​​​​​​​​
  ]

Any Help will be appreciated!!


Solution

  • Quick fixes in your query,

    universities:

    • $addFields, remove $project and add only one operation for isMarked
    • $unwind deconstruct dept array
    • $group by dept and get values array of root

    findDistinct:

    • $group by null and get unique courses array and status
    • $reduce to iterate loop of Courses nested array and get unique array using $setUnion
    • Make array of course and status in dest field
    • $unwind deconstruct dest array
    • $replaceRoot replace dest object to root
    db.collection.aggregate([
      { $match: { university: "SPYU" }
      },
      {
        $facet: {
          universities: [
            { $addFields: { isMarked: { $in: ["French", "$Courses"] } } },
            { $unwind: "$dept" },
            {
              $group: {
                _id: "$dept",
                values: { $push: "$$ROOT" }
              }
            }
          ],
          findDistinct: [
            {
              $group: {
                _id: null,
                Courses: { $addToSet: "$Courses" },
                Status: { $addToSet: "$status" }
              }
            },
            {
              $project: {
                _id: 0,
                dist: [
                  {
                    name: "Courses",
                    values: {
                      $reduce: {
                        input: "$Courses",
                        initialValue: [],
                        in: { $setUnion: ["$$this", "$$value"] }
                      }
                    }
                  },
                  {
                    name: "Status",
                    values: "$Status"
                  }
                ]
              }
            },
            { $unwind: "$dist" },
            { $replaceRoot: { newRoot: "$dist" } }
          ]
        }
      }
    ])
    

    Playground