Reputation: 23
I have a Accounts collection where details about posts are denormalized into. In each account document, there is a pages field which is an array of subdocument containing information about a post. Each post document has a tag field, given a account id, I am trying to get the pages in the account with appropriate tag grouping, the only problem is, I want grouped documents as siblings of ungrouped ones.
Example :
{
_id : "account1",
pages : [
{
title : "New Page"
tag : "novel",
},
{
title : "Another New Page"
tag : "novel",
},
{
title : "One more New Page"
}
]
}
My query looks like this
db.accounts.aggregate([
{
$match : {
_id : "account1"
}
},
{
$unwind: "$pages"
},
{
$project: {
pages: 1,
tag: {
$ifNull : ["$pages.tag", "unassigned"]
}
}
},
{
$group: {
_id: "$tag",
pages: {
$push: "$pages"
}
}
}
])
Currently, the output looks like this
{
"_id" : "novel",
"pages" : [
{
title : "New Page"
tag : "novel",
},
{
title : "Another New Page"
tag : "novel",
}
]
},
{
"_id" : "unassigned",
"pages" : [
{
title : "One more New Page"
tag : "unassigned",
}
]
}
But I need to unwrap this unassigned grouping,the output should be like
{
"_id" : "novel",
"pages" : [
{
title : "New Page"
tag : "novel",
},
{
title : "Another New Page"
tag : "novel",
}
]
},
{
title : "One more New Page"
}
Upvotes: 2
Views: 96
Reputation: 3010
The following query can get us the expected output:
db.accounts.aggregate([
{
$match : {
_id : "account1"
}
},
{
$unwind: "$pages"
},
{
$project: {
pages: 1,
tag: {
$ifNull : ["$pages.tag", "unassigned"]
}
}
},
{
$group: {
_id: "$tag",
pages: {
$push: "$pages"
}
}
},
{
$addFields:{
"data":{
$cond:[
{
$eq:["$_id","unassigned"]
},
"$pages",
[]
]
}
}
},
{
$unwind:{
"path":"$data",
"preserveNullAndEmptyArrays":true
}
},
{
$addFields:{
"data":{
$cond:[
{
$eq:["$_id","unassigned"]
},
"$data",
"$$ROOT"
]
}
}
},
{
$replaceRoot:{
"newRoot":"$data"
}
}
]).pretty()
Data set:
{
"_id" : "account1",
"pages" : [
{
"title" : "New Page",
"tag" : "novel"
},
{
"title" : "Another New Page",
"tag" : "novel"
},
{
"title" : "One more New Page"
},
{
"title" : "New page 2"
},
{
"title" : "New page 3"
}
]
}
Output:
{ "title" : "One more New Page" }
{ "title" : "New page 2" }
{ "title" : "New page 3" }
{
"_id" : "novel",
"pages" : [
{
"title" : "New Page",
"tag" : "novel"
},
{
"title" : "Another New Page",
"tag" : "novel"
}
]
}
Explanation: After the pages are grouped on the basis of tags, the unassigned pages are projected as a new field data
. We would then unwind the array. Later on, the documents with tags are also assigned to data
field i.e the data
now contains both unassigned pages and group of assigned pages. Finally, we can project data
as root document.
Upvotes: 1