I have a projects collection with documents such as this:
{
"_id" : ObjectId("589eff3fee3d13019843f55a"),
"name" : "Project A",
"desc" : "test",
"numofvms" : 0,
"templates" : [
{
"_id" : ObjectId("589e4c14ee3d131bac8b403c")
},
{
"_id" : ObjectId("589e4c1dee3d131bac8b403d")
}
],
"nodes" : [
{
"_id" : ObjectId("589eff8f2bb59057c3f9b89d"),
"name" : "Node A"
},
{
"_id" : ObjectId("589eff962bb59057c3f9b89e"),
"name" : "Node B"
},
{
"_id" : ObjectId("589eff982bb59057c3f9b89f"),
"name" : "Node C"
},
{
"_id" : ObjectId("589eff9a2bb59057c3f9b8a0"),
"name" : "Node D"
}
],
"links" : [ ]
}
I try to receive the array of subdocuments (nodes field) for a given document (project), but without the root document. The result should look like this:
[
{
"_id" : ObjectId("589eff8f2bb59057c3f9b89d"),
"name" : "Node A"
},
{
"_id" : ObjectId("589eff962bb59057c3f9b89e"),
"name" : "Node B"
},
{
"_id" : ObjectId("589eff982bb59057c3f9b89f"),
"name" : "Node C"
},
{
"_id" : ObjectId("589eff9a2bb59057c3f9b8a0"),
"name" : "Node D"
}
]
I tried different approaches like the one below but could not get rid of the root document:
> db.projects.find({_id: ObjectId("589eff3fee3d13019843f55a")}, { "nodes": 1, _id: 0 }).pretty()
{
"nodes" : [
{
"_id" : ObjectId("589eff8f2bb59057c3f9b89d"),
"name" : "Node A"
},
{
"_id" : ObjectId("589eff962bb59057c3f9b89e"),
"name" : "Node B"
},
{
"_id" : ObjectId("589eff982bb59057c3f9b89f"),
"name" : "Node C"
},
{
"_id" : ObjectId("589eff9a2bb59057c3f9b8a0"),
"name" : "Node D"
}
]
}
Can this be achieved directly in the query or do I have to extract the array manually in my application?
Try this:
db.collection.aggregate([
{
$unwind: '$nodes'
},
{
$match: {_id: ObjectId("589eff3fee3d13019843f55a") }
},
{
$replaceRoot: { newRoot: "$nodes" }
}
]).toArray();
And you will get
[
{
"_id" : ObjectId("589eff8f2bb59057c3f9b89d"),
"name" : "Node A"
},
{
"_id" : ObjectId("589eff962bb59057c3f9b89e"),
"name" : "Node B"
},
{
"_id" : ObjectId("589eff982bb59057c3f9b89f"),
"name" : "Node C"
},
{
"_id" : ObjectId("589eff9a2bb59057c3f9b8a0"),
"name" : "Node D"
}
]
$unwind operator is to deconstruct nodes field from the input documents to output a document for each element.
And then use the $replaceRoot stage to promote the nodes document to the top level, discarding the current top level fields.
Hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With