简体   繁体   中英

How do I produce the union of embedded arrays in mongodb aggregate

I have a set of documents of the form:

{
    skill_id: 2,
    skill_recs: [
        {
            _id: 4,
            member_ids: [1, 4, 5]
        }
    ]
},
{
    skill_id: 5,
    skill_recs: [
        {
            _id: 4,
            member_ids: [1, 7, 9]
        }
    ]
}

Now I want to aggregate a set of these documents such that skill_recs are combined by _id and the member_ids of all combined docs are merged into a single union of values...

{ _id: 4,
  member_ids: [1, 4, 5, 7, 9]
}

I get most of the way with:

db.aggregate([
    {
        $unwind: '$skill_recs'
    },
    {
        $group: {
            _id: '$skill_recs._id',
            all_member_ids: {$push: '$skill_recs.member_ids'}
        }
    },
    {
        $addFields: {
            member_ids: {$setUnion: '$all_member_ids'}
        }
    }
])

but the $setUnion doesn't do a union of the array of arrays that it is passed.

Instead it produces:

{ _id: 4,
  member_ids: [[1, 4, 5], [1, 7, 9]]
}

Any way to produce the union of these arrays?

You're quite close, Here's a quick example of how to achieve this using $reduce

db.collection.aggregate([
  {
    $unwind: "$skill_recs"
  },
  {
    $group: {
      _id: "$skill_recs._id",
      all_member_ids: {
        $push: "$skill_recs.member_ids"
      }
    }
  },
  {
    $addFields: {
      member_ids: {
        $reduce: {
          input: "$all_member_ids",
          initialValue: [],
          in: {
            $setUnion: [
              "$$this",
              "$$value"
            ]
          }
        }
      }
    }
  }
])

Mongo Playground

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM