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