2

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

3
  • Find returns a whole document that matches the conditions. In your case the conditions are: fid equals to some id, and ch has at least one sub-document with trashed equals to false. You need to either process the result on the client side, or use aggregation framework. Commented Sep 4, 2017 at 11:41
  • What's the expected result ? One big array with all ch items where trashed is false ? Several documents with filtered ch array ? you should post the ChildParentsData structure to make it clearer Commented Sep 4, 2017 at 11:58
  • Thank you @felix , I have already added the struct Commented Sep 4, 2017 at 12:08

2 Answers 2

2

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)
Sign up to request clarification or add additional context in comments.

Comments

0

An quick way to get the particular fields instead of all the fileds is using projection. An example of golang is here:

    filter := bson.D{{"_id" , bson.ObjectIdHex("59ad187a6b9600120bd03a53")}}
    projection := bson.D{{"ch", 0}}
    collection.FindOne(context.TODO(), filter, options.FindOne())

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.