skip to Main Content

I have the collection sessions:

[
    {
      "_id": "",
      "members": [
        { "user_id": "11", "joined_at": "2023-06-15T04:50:06.298Z" },
        { "user_id": "23", "joined_at": "2023-06-15T04:50:06.298Z" },
        { "user_id": "73", "joined_at": "2023-06-15T04:50:06.298Z" }
      ]
    },
    {
      "_id": "",
      "members": [
        { "user_id": "59", "joined_at": "2023-06-15T04:50:06.298Z" },
        { "user_id": "37", "joined_at": "2023-06-15T04:50:06.298Z" },
        { "user_id": "11", "joined_at": "2023-06-15T04:50:06.298Z" }
      ]
    },
    {
      "_id": "",
      "members": [
        { "user_id": "11", "joined_at": "2023-06-15T04:50:06.298Z" },
        { "user_id": "23", "joined_at": "2023-06-15T04:50:06.298Z" },
        { "user_id": "28", "joined_at": "2023-06-15T04:50:06.298Z" }
      ]
    }
]

I want to get all distinct user_id values from the entire collection (or based on a filter). Based on the documents above, the intended results should be:

["11", "23", "73", "59", "37", "28"]

I know that the collection.distinct() function exists, but I’d like to see how it’s done for objects fields in an array.

2

Answers


    1. $group – Group all documents and add the members.user_id array into the user_ids array. This results in the user_ids being a nested array.

    2. $set – Set user_ids field.

      2.1. $setUnion – Union the elements from the result 2.1.1. This results in the elements are distinct.

      2.1.1. $reduce – Flatten the nested array user_ids.

    db.collection.aggregate([
      {
        $group: {
          _id: null,
          user_ids: {
            $addToSet: "$members.user_id"
          }
        }
      },
      {
        $set: {
          user_ids: {
            $setUnion: {
              $reduce: {
                input: "$user_ids",
                initialValue: [],
                in: {
                  $concatArrays: [
                    "$$value",
                    "$$this"
                  ]
                }
              }
            }
          }
        }
      }
    ])
    

    Demo @ Mongo Playground

    Login or Signup to reply.
  1. /*
      Expected Output:
      [
        {
          members: ['11', '23', '73', '59', '37', '28'],
        },
      ]
    
      step 1: unwind members
      step 2: group by null and add to set members.user_id
      step 3: project members
      
    */
    
    db.collection.aggregate([
      {
        $unwind: '$members',
      },
      {
        $group: {
          _id: null,
          members: {
            $addToSet: '$members.user_id',
          },
        },
      },
      {
        $project: {
          _id: 0,
          members: 1,
        },
      },
    ]);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search