Reputation: 51
I have a ClientField collection with a property map_type
which can be "conversion", "default", or "json". I would like to group all client fields by map_type and have the result be an object rather than an array. Is this possible to do using only the Mongodb aggregate pipeline?
//Example ClientField Object
{
"client_name" : "StackOverflow",
"map_type" : "conversion",
"push_type" : "profile",
"name" : "dateOfBirth",
"conversion" : {
"method" : "dateOfBirth",
"params" : "dateOfBirth"
},
"json_path" : "dateOfBirth",
"e_field_id" : "4",
}
My current aggregate pipeline is:
const fieldGroups = await ClientField.aggregate([
{ $match: { client_name: this.name, push_type: push_type } },
{ $group: { _id: "$map_type", fields: { $push: "$$ROOT" } } }
]);
which returns an array of groups with a fields
array:
[
{ _id: 'default', fields: [ContactField] },
{ _id: 'conversion', fields: [ContactField] },
{ _id: 'json', fields: [ContactField] }
]
My desired result is:
{
default: [ClientField],
conversion: [ClientField],
json: [ClientField]
}
Upvotes: 1
Views: 1521
Reputation: 49975
You need to collect all your grouping results into one document by using another $group. Then you can run $arrayToObject to set your previous stage grouping _id
as key and run $replaceRoot to promote that new object to top level:
db.collection.aggregate([
// $match
{
$group: {
_id: "$map_type",
fields: {
$push: "$$ROOT"
}
}
},
{
$group: {
_id: null,
root: { $push: { k: "$_id", v: "$fields" } }
}
},
{
$replaceRoot: { newRoot: { $arrayToObject: "$root" } }
}
])
Upvotes: 1