Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

reshape an element to an array after unwinding it

I have a collection that looks like this

{ name: 'ABC', metadata.tables: [ { name: 'table1' }] }

Basically I want to query within the metadata.tables array to look for an elemMatch on the name of the table. I can do that using the aggregation pipeline by first unwinding the metadata.tables array and then doing the $match on table name. This works fine but now the metadata.tables becomes an object instead of an array. This is how the query looks like

db.source.aggregate([ 
 { "$unwind": "$metadata.tables" }, 
 { $match: { "metadata.tables.name": "table 1" } }
])

The returned document looks like this

{
 "_id": "......",
 "metadata": {
  "tables": {
  }
 }
}

Notice the tables are now an object instead of an array. I understand why unwind changes it to an object but how can I revert it back to an array with a single element in it (the matching table).

Thanks

like image 960
adeelmahmood Avatar asked Jan 21 '26 15:01

adeelmahmood


1 Answers

Just Perform a $group with a $push:

db.source.aggregate([ 
 { "$unwind": "$metadata.tables" }, 
 { "$match": { "metadata.tables.name": "table 1" } },
 { "$group": {
     "_id": "$_id",
     "name": { "$first": "$name" },
     "tables": { "$push": "$metadata.tables" }
 }},
 { "$project": {
     "name": 1,
     "metadata": {
         "tables": "$tables"
     }
 }}
])

And optionally $project since aggregation accumulators cannot use an embedded field for output and you would need to rename much like as is shown.

Optionally you could use $map if you knew you only had or just wanted a single element out of each "unwound" document:

db.source.aggregate([ 
 { "$unwind": "$metadata.tables" }, 
 { "$match": { "metadata.tables.name": "table 1" } },
 { "$project": {
     "name": 1,
     "metadata": {
         "tables": {
             "$map": {
                 "input": ["A"],
                 "as": "el",
                 "in": "$metdata.tables"
             }
         }
     }
 }}
])

Which would essentially substitute the single element array provided to "input" with the value of the field.

like image 189
Blakes Seven Avatar answered Jan 25 '26 18:01

Blakes Seven



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!