简体   繁体   中英

How to merge an array field in multiple documents into a single output array in MongoDB and mongoexport to csv

I have a MongoDB collection, Groups. Each group has an array of members, referenced by the member's unique id. A user can be a member of many groups.

Group data looks like this:

{ _id: 1, members: ['1', '3', '5'], status: 'active' }
{ _id: 2, members: ['4', '1', '10', '11'], status: 'inactive' }
{ _id: 3, members: ['1', '2', '9'], status: 'active' }

I'm trying to extract all members of active groups as a single array of member ids, without duplication. I want to export them to a csv file using mongoexport.

I can export the ids of the relevant projects and their member lists:

mongoexport -h localhost:3001 --db mydbname --collection groups --type=csv --fields _id,members --query '{"status": "active"}' --out mongotestoutput.txt

But I can't figure out how to merge the member lists into a single array. I've been looking at Aggregation but I'm just getting lost among all the different options, I can't see which one would do what I need. Very grateful for any help.

Use aggregation with $unwind and then $out to create a new collection that looks like you need. Then export this new collection to CSV file.

db.test1.insertMany([
  { _id: 1, members: ['1', '3', '5'], status: 'active' },
  { _id: 2, members: ['4', '1', '10', '11'], status: 'inactive' },
  { _id: 3, members: ['9'], status: 'active' }
])

{_id:0} here and below is used to suppress _id field

db.test1.aggregate([
  {$unwind: "$members"},
  {$project:{_id:0}},
  {$out:"test2"}
])


db.test2.find({},{_id:0})
{ "members" : "1", "status" : "active" }
{ "members" : "3", "status" : "active" }
{ "members" : "5", "status" : "active" }
{ "members" : "4", "status" : "inactive" }
{ "members" : "1", "status" : "inactive" }
{ "members" : "10", "status" : "inactive" }
{ "members" : "11", "status" : "inactive" }
{ "members" : "9", "status" : "active" }

Or if you need to get members by status in the array - add another $group , $addToSet stage:

db.test1.aggregate([
  {$unwind: "$members"},
  {$project:{_id:0}},
  { "$group": { "_id": "$status", members:{$addToSet:"$members"} } },
  {$out:"test3"}
])

db.test3.find()
{ "_id" : "inactive", "members" : [ "4", "1", "10", "11" ] }
{ "_id" : "active", "members" : [ "1", "3", "5", "9" ] }

See MongoPlayground

This question shows two ways to get the result I'm looking for. The accepted answer uses push, reduce and setUnion. The newer answer is simpler, using unwind and addToSet. Both work for me but I'm going with the simpler version:

db.collection.aggregate([
  { $match: { "status": "active" },
  { $unwind: "$members"},
  { $group:{
     _id: 0,
     selectedMembers: { $addToSet: '$members' }      
  }}
])

I'm extracting the array I want from the JSON object returned by this expression.

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