1

I have data that has user primary keys in "user.pk", and "usertags.user.pk".

[
  {
    _id: ObjectId("62015250cb18d3cadb32c38e"),
    user: { pk: '7485070525' },
    usertags: [ { user: { pk: '334777488' } } ]
  },
  {
    _id: ObjectId("62015250cb18d3cadb32c38f"),
    user: { pk: '334777488' },
    usertags: [
      { user: { pk: '7485070525' } },
      { user: { pk: '271738610' } },
      { user: { pk: '31961021' } }
    ]
  }
]

I am looking to aggregate all this data into a single list of all distinct user primary keys, so the result for the data above would be something like { _id: null, user_pks: [7485070525, 334777488, 271738610, 31961021] }

I tried using the $group aggregation, but I can't figure out how to merge "user.pk", and "usertags.user.pk". Can anyone help me with that?

Edit: This is the closest I've gotten, which puts users and usertags in separate lists.

db.collection.aggregate([
  { $unwind: "$usertags" },
  { $group: { _id: null, users: { $push: "$user.pk" }, usertags: {$push: "$usertags.user.pk" } } },
])

1 Answer 1

1

you can do this:

test it here mongodb playground

db.collection.aggregate([
  {
    $group: {
      _id: null,
      user_pk: {
        $push: "$user.pk"
      },
      user_sub_pk: {
        $push: "$usertags"
      }
    },
    
  },
  // flattern array in user_sub_pk
  {
    $set: {
      user_sub_pk: {
        $reduce: {
          input: "$user_sub_pk",
          initialValue: [],
          in: {
            $concatArrays: [
              "$$value",
              "$$this"
            ],
            
          },
          
        },
        
      },
      
    },
    
  },
  {
    $project: {
      user_pks: {
        $concatArrays: [
          "$user_pk",
          "$user_sub_pk.user.pk"
        ],
        
      },
      
    },
    // remove duplicate items
    {
    "$project": {
      "user_pks": {
        "$setUnion": [
          "$user_pks",
          []
        ]
      }
    }
  }
    
  }
])

update: refactored by @zrbecker

db.collection.aggregate([
  {
    $group: {
      _id: null,
      users: {
        $push: "$user.pk"
      },
      usertags: {
        $push: "$usertags.user.pk"
      }
    }
  },
  {
    $project: {
      users: {
        $setUnion: [
          "$users",
          {
            $reduce: {
              input: "$usertags",
              initialValue: [],
              in: {
                $concatArrays: [
                  "$$value",
                  "$$this"
                ]
              }
            }
          }
        ]
      }
    }
  }
])
Sign up to request clarification or add additional context in comments.

2 Comments

This is awesome, looks like the direction I need to go. However, something is wrong with the reduce stage. It doesn't grab the elements from the usertags in the first document. Here is a demonstration mongoplayground.net/p/TfYVJEbBgm7 I changed the usertag to 1234 and its not in the result.
This seems to have done it mongoplayground.net/p/KfzILnYQR0X

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.