In my case I have a collection where I have stored a data with a structure that below
{
"_id" : ObjectId("59ad187a0447d3617fb802b8"),
"fid" : ObjectId("59ad187a6b9600120bd03a53"),
"pr" : [
{
"_id" : ObjectId("59ad187a6b9600120bd03a53"),
"trashed" : false
}
],
"ch" : [
{
"_id" : ObjectId("59ad18a36b9600120bd03a57"),
"trashed" : false
},
{
"_id" : ObjectId("59ad18a36b9600120bd03a99"),
"trashed" : false
},
{
"_id" : ObjectId("59ad18a36b9600120bd03a98"),
"trashed" : true
},
{
"_id" : ObjectId("59ad18a36b9600120bd03a97"),
"trashed" : false
}
]
}
So I want to get all objects in ch
where trashed is false
Here is my query
type ChildParentsData struct {
Id bson.ObjectId `json:"_id,omitempty" bson:"_id,omitempty"`
Trashed bool `json:"trashed" bson:"trashed"`
}
var tree []ChildParentsData
err := Connection.Session.DB("cctv_storage").C("tree").Find(
bson.M{
"fid": bson.ObjectIdHex(id), "ch.trashed": false
}).Select(
bson.M{
"ch.$": 1
}).All(&tree)
But as a response I am getting all data, but I need only objects
in ch
You can achieve this using the aggregation framework, thanks to the $replaceRoot
operator introduced in MongoDB 3.4
We first get matching documents for the specific fid
, then we unwind the array and remove docmuments where ch.trashed
is true. Finally, we remove the ch
field by promoting the content of ch
as root of the document
Here is the code to achieve this:
type ChildParentsData struct {
Id bson.ObjectId `json:"_id,omitempty" bson:"_id,omitempty"`
Trashed bool `json:"trashed" bson:"trashed"`
}
var tree []ChildParentsData
pipeline := []bson.M{
{"$match": bson.M{"fid": bson.ObjectIdHex("59ad187a6b9600120bd03a53")}},
{"$unwind": "$ch"},
{"$match": bson.M{"ch.trashed": false}},
{"$replaceRoot": bson.M{"newRoot": "$ch"}}}
err = Connection.Session.DB("cctv_storage").C("tree").Pipe(pipeline).All(&tree)
if err != nil {
fmt.Printf("error: %v", err)
os.Exit(0)
}
fmt.Printf("doc: %v", tree)