Search code examples
mongodbselectgomgo

Golang , mongodb can not do select


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


Solution

  • 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)